Skip to content

Commit a62df69

Browse files
committed
feat: updates to admin section
1 parent 81a6269 commit a62df69

File tree

4 files changed

+221
-65
lines changed

4 files changed

+221
-65
lines changed
+119-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,120 @@
1-
from django.contrib import admin
1+
from django.conf import settings
2+
from django.contrib import admin, messages
23

3-
# Register your models here.
4+
from .models import Activity, ActivityImage, ActivityMakingStep, Image
5+
from .tasks import delete_file_task
6+
7+
8+
class ActivityAdmin(admin.ModelAdmin):
9+
list_display = ("title", "id", "created_on", "publish")
10+
list_filter = (
11+
"created_on",
12+
"publish",
13+
)
14+
search_fields = (
15+
"title",
16+
"id",
17+
"category",
18+
)
19+
ordering = ["-created_on"]
20+
actions = ["publish", "un_publish", "delete_selected"]
21+
22+
def un_publish(self, request, queryset):
23+
"""
24+
This function is used to unpublish selected activities
25+
"""
26+
queryset.update(publish=False)
27+
messages.success(request, "Selected records were unpublished successfully.")
28+
29+
def publish(self, request, queryset):
30+
"""
31+
This function is used to publish selected activities
32+
"""
33+
queryset = queryset.filter(publish=False)
34+
queryset.update(publish=True)
35+
messages.success(request, "Selected records were published successfully.")
36+
37+
def delete_selected(self, request, queryset):
38+
"""
39+
This function is used to delete selected activities
40+
"""
41+
queryset.delete()
42+
messages.success(request, "Selected records were deleted successfully.")
43+
44+
un_publish.short_description = "Unpublish selected activities"
45+
publish.short_description = "Publish selected activities"
46+
delete_selected.short_description = "Delete selected activities"
47+
48+
def get_readonly_fields(self, request, obj=None):
49+
return ["id", "created_on", "views_count", "saved_by", "views"]
50+
51+
def save_model(self, request, obj, form, change):
52+
super().save_model(request, obj, form, change)
53+
54+
if change:
55+
old = Activity.objects.get(pk=obj.pk)
56+
new = Activity.objects.get(pk=obj.pk)
57+
58+
if (
59+
old.video.find("cloudinary.com") > -1
60+
or old.video.startswith(
61+
"{0}://{1}".format(
62+
settings.DEFAULT_MEDIA_SERVER_PROTOCOL,
63+
settings.DEFAULT_MEDIA_SERVER_DOMAIN,
64+
)
65+
)
66+
) and old.video != new.video:
67+
delete_file_task.delay(old.video)
68+
69+
70+
class ActivityImageAdmin(admin.ModelAdmin):
71+
search_fields = ["activity__title", "activity__id", "image__public_id"]
72+
list_display = ["activity", "image"]
73+
74+
def delete_model(self, request, obj):
75+
"""
76+
This function is used to delete the activity image
77+
"""
78+
delete_file_task.delay(obj.image.file_url)
79+
obj.delete()
80+
81+
def delete_queryset(self, request, queryset):
82+
"""
83+
This function is used to delete the activity image
84+
"""
85+
for obj in queryset:
86+
delete_file_task.delay(obj.image.file_url)
87+
queryset.delete()
88+
89+
90+
class ImageAdmin(admin.ModelAdmin):
91+
search_fields = ["public_id"]
92+
list_display = ["public_id", "file_url"]
93+
94+
def delete_model(self, request, obj):
95+
"""
96+
This function is used to delete the image
97+
"""
98+
delete_file_task.delay(obj.file_url)
99+
obj.delete()
100+
101+
102+
class ActivityMakingStepAdmin(admin.ModelAdmin):
103+
search_fields = ["activity__title", "title"]
104+
list_display = ["activity", "title"]
105+
list_filter = ["activity", "title"]
106+
107+
def delete_model(self, request, obj):
108+
"""
109+
This function is used to delete the activity making step
110+
"""
111+
for img in obj.image.all():
112+
delete_file_task.delay(img.file_url)
113+
img.delete()
114+
obj.delete()
115+
116+
117+
admin.site.register(Activity, ActivityAdmin)
118+
admin.site.register(ActivityImage, ActivityImageAdmin)
119+
admin.site.register(Image, ImageAdmin)
120+
admin.site.register(ActivityMakingStep, ActivityMakingStepAdmin)

zubhub_backend/zubhub/activities/models.py

+66-63
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import uuid
2-
from django.db import models
2+
from math import floor
3+
34
from django.contrib.auth import get_user_model
4-
from django.utils.text import slugify
5+
from django.db import models
56
from django.utils import timezone
6-
from math import floor
7-
from projects.models import Category
7+
from django.utils.text import slugify
88

99
Creator = get_user_model()
1010

@@ -17,16 +17,14 @@ def __str__(self):
1717
try:
1818
image = self.file_url
1919
except AttributeError:
20-
image = ''
20+
image = ""
2121
return "Photo <%s:%s>" % (self.public_id, image)
2222

2323

2424
class InspiringArtist(models.Model):
25-
'''this should be having more fields to distinguish an artist '''
26-
image = models.ForeignKey(Image,
27-
on_delete=models.CASCADE,
28-
null=True,
29-
blank=True)
25+
"""this should be having more fields to distinguish an artist"""
26+
27+
image = models.ForeignKey(Image, on_delete=models.CASCADE, null=True, blank=True)
3028
short_biography = models.TextField(max_length=10000, blank=True, null=True)
3129
name = models.CharField(max_length=100, null=True)
3230

@@ -35,41 +33,43 @@ def __str__(self):
3533

3634

3735
class Activity(models.Model):
38-
id = models.UUIDField(primary_key=True,
39-
default=uuid.uuid4,
40-
editable=False,
41-
unique=True)
42-
creators = models.ManyToManyField(Creator,
43-
related_name="activities_created")
36+
id = models.UUIDField(
37+
primary_key=True, default=uuid.uuid4, editable=False, unique=True
38+
)
39+
creators = models.ManyToManyField(Creator, related_name="activities_created")
4440
title = models.CharField(max_length=500)
45-
category = models.ManyToManyField("projects.Category",blank=True, related_name="activities")
46-
introduction = models.CharField(max_length=10000,blank=True)
41+
category = models.ManyToManyField(
42+
"projects.Category", blank=True, related_name="activities"
43+
)
44+
introduction = models.CharField(max_length=10000, blank=True)
4745
class_grade = models.CharField(max_length=50, blank=True)
48-
46+
4947
learning_goals = models.TextField(max_length=10000, blank=True, null=True)
5048
facilitation_tips = models.TextField(max_length=10000, blank=True, null=True)
5149
motivation = models.TextField(max_length=10000, blank=True, null=True)
5250
video = models.URLField(max_length=1000, blank=True, null=True)
5351
materials_used = models.TextField(max_length=5000, blank=True, null=True)
54-
materials_used_image = models.ForeignKey(Image,
55-
on_delete=models.SET_NULL,
56-
null=True,
57-
blank=True,
58-
)
59-
inspiring_artist = models.ForeignKey(InspiringArtist,
60-
on_delete=models.SET_NULL,
61-
null=True,
62-
related_name="inspiring_artist_activities",
63-
blank=True,
64-
)
65-
views = models.ManyToManyField(Creator,
66-
blank=True,
67-
related_name="activities_viewed")
52+
materials_used_image = models.ForeignKey(
53+
Image,
54+
on_delete=models.SET_NULL,
55+
null=True,
56+
blank=True,
57+
)
58+
inspiring_artist = models.ForeignKey(
59+
InspiringArtist,
60+
on_delete=models.SET_NULL,
61+
null=True,
62+
related_name="inspiring_artist_activities",
63+
blank=True,
64+
)
65+
views = models.ManyToManyField(
66+
Creator, blank=True, related_name="activities_viewed"
67+
)
6868
views_count = models.IntegerField(blank=True, default=0)
6969
saved_count = models.IntegerField(blank=True, default=0)
70-
saved_by = models.ManyToManyField(Creator,
71-
blank=True,
72-
related_name="activities_saved")
70+
saved_by = models.ManyToManyField(
71+
Creator, blank=True, related_name="activities_saved"
72+
)
7373
created_on = models.DateTimeField(default=timezone.now, null=True)
7474
publish = models.BooleanField(default=False, null=True)
7575
slug = models.SlugField(unique=True, max_length=1000)
@@ -79,56 +79,59 @@ def save(self, *args, **kwargs):
7979
pass
8080
else:
8181
uid = str(uuid.uuid4())
82-
uid = uid[0:floor(len(uid) / 6)]
82+
uid = uid[0 : floor(len(uid) / 6)]
8383
self.slug = slugify(self.title) + "-" + uid
8484

8585
super().save(*args, **kwargs)
8686

8787
def __str__(self):
8888
return self.title
8989

90+
class Meta:
91+
verbose_name_plural = "Activities"
92+
9093

9194
class InspiringExample(models.Model):
92-
activity = models.ForeignKey(Activity,
93-
on_delete=models.CASCADE,
94-
null=True,
95-
related_name="inspiring_examples",
96-
blank=True)
95+
activity = models.ForeignKey(
96+
Activity,
97+
on_delete=models.CASCADE,
98+
null=True,
99+
related_name="inspiring_examples",
100+
blank=True,
101+
)
97102
description = models.TextField(max_length=10000, blank=True)
98103
credit = models.TextField(max_length=1000, blank=True)
99-
image = models.ForeignKey(Image,
100-
on_delete=models.CASCADE,
101-
null=True,
102-
blank=True)
104+
image = models.ForeignKey(Image, on_delete=models.CASCADE, null=True, blank=True)
103105

104106
def __str__(self):
105107
return self.image
106108

107109

108110
class ActivityImage(models.Model):
109-
activity = models.ForeignKey(Activity,
110-
on_delete=models.CASCADE,
111-
null=True,
112-
related_name="activity_images",
113-
blank=True)
114-
image = models.ForeignKey(Image,
115-
on_delete=models.CASCADE,
116-
null=True,
117-
blank=True)
111+
activity = models.ForeignKey(
112+
Activity,
113+
on_delete=models.CASCADE,
114+
null=True,
115+
related_name="activity_images",
116+
blank=True,
117+
)
118+
image = models.ForeignKey(Image, on_delete=models.CASCADE, null=True, blank=True)
118119

119120
def __str__(self):
120121
return self.image
121122

122123

123124
class ActivityMakingStep(models.Model):
124-
activity = models.ForeignKey(Activity,
125-
on_delete=models.CASCADE,
126-
null=True,
127-
related_name="making_steps",
128-
blank=True)
129-
130-
title = models.TextField(max_length=500,null=True)
131-
image = models.ManyToManyField(Image,blank=True)
125+
activity = models.ForeignKey(
126+
Activity,
127+
on_delete=models.CASCADE,
128+
null=True,
129+
related_name="making_steps",
130+
blank=True,
131+
)
132+
133+
title = models.TextField(max_length=500, null=True)
134+
image = models.ManyToManyField(Image, blank=True)
132135
description = models.TextField(max_length=10000, blank=True)
133136
step_order = models.IntegerField()
134137

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import os
2+
3+
from django.conf import settings
4+
from django.db.models.signals import pre_delete
5+
from django.dispatch import receiver
6+
7+
from .models import Activity, ActivityImage, Image
8+
9+
10+
@receiver(pre_delete, sender=Activity)
11+
def delete_activity_images(sender, instance, **kwargs):
12+
ActivityImage.objects.filter(activity=instance).delete()
13+
14+
images = Image.objects.filter(activity=instance)
15+
for image in images:
16+
if os.path.isfile(os.path.join(settings.MEDIA_ROOT, str(image.file))):
17+
os.remove(os.path.join(settings.MEDIA_ROOT, str(image.file)))
18+
images.delete()
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from random import uniform
2+
3+
from celery import shared_task
4+
5+
6+
@shared_task(bind=True, acks_late=True, max_retries=10)
7+
def delete_file_task(self, url):
8+
from zubhub.utils import delete_file_from_media_server
9+
10+
try:
11+
res = delete_file_from_media_server(url)
12+
13+
res = res.json()
14+
if res["result"] != "ok" and res["result"]["HTTPStatusCode"] != 204:
15+
raise Exception()
16+
17+
except Exception as e:
18+
raise self.retry(exc=e, countdown=int(uniform(2, 4) ** self.request.retries))

0 commit comments

Comments
 (0)