Skip to content

Commit

Permalink
[backend] add activity to admin management
Browse files Browse the repository at this point in the history
* minor modifications to the admin model
* add admin models management to admin.py
* implement effective signals to handle
  admin models instances, addition,
  modification and deletion with proper
  cleanup

Issue: #1094
Signed-off-by: Ndibe Raymond Olisaemeka <rolisaemeka-ctr@wikimedia.org>
  • Loading branch information
Ndibe Raymond Olisaemeka committed Jul 17, 2024
1 parent b1b7c8b commit e07229b
Show file tree
Hide file tree
Showing 6 changed files with 414 additions and 155 deletions.
103 changes: 101 additions & 2 deletions zubhub_backend/zubhub/activities/admin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,102 @@
from django.contrib import admin
from django.contrib import admin, messages

# Register your models here.
from .models import (
Activity,
ActivityImage,
ActivityMakingStep,
Image,
InspiringArtist,
InspiringExample,
)


class InlineActivityImages(admin.StackedInline):
model = ActivityImage


class InlineActivityMakingSteps(admin.StackedInline):
model = ActivityMakingStep


class InlineInspiringExamples(admin.StackedInline):
model = InspiringExample


class InspiringArtistAdmin(admin.ModelAdmin):
search_fields = ("name",)
list_display = (
"name",
"image",
)
list_filter = ("name",)


class ActivityAdmin(admin.ModelAdmin):
list_display = ("title", "id", "created_on", "publish")
list_filter = (
"created_on",
"publish",
)
search_fields = (
"title",
"id",
"category",
)
ordering = ["-created_on"]
actions = ["publish", "un_publish", "delete_selected"]
inlines = [InlineActivityImages, InlineActivityMakingSteps, InlineInspiringExamples]
list_per_page = 50 # paginate when more than 50 items

def un_publish(self, request, queryset):
"""
This function is used to unpublish selected activities
"""
queryset.update(publish=False)
messages.success(request, "Selected records were unpublished successfully.")

def publish(self, request, queryset):
"""
This function is used to publish selected activities
"""
queryset = queryset.filter(publish=False)
queryset.update(publish=True)
messages.success(request, "Selected records were published successfully.")

def delete_selected(self, request, queryset):
"""
This function is used to delete selected activities
"""
queryset.delete()
messages.success(request, "Selected records were deleted successfully.")

def get_readonly_fields(self, request, obj=None):
return [
"id",
"created_on",
"views_count",
"saved_by",
"views",
"saved_count",
"slug",
]

un_publish.short_description = "Unpublish selected activities"
publish.short_description = "Publish selected activities"
delete_selected.short_description = "Delete selected activities"


class ActivityImageAdmin(admin.ModelAdmin):
search_fields = ["activity__title", "activity__id", "image__public_id"]
list_display = ["activity", "image"]


class ImageAdmin(admin.ModelAdmin):
search_fields = ["public_id"]
list_display = ["public_id", "file_url"]
# should not be able to edit this from the admin panel ?


admin.site.register(InspiringArtist, InspiringArtistAdmin)
admin.site.register(Activity, ActivityAdmin)
admin.site.register(ActivityImage, ActivityImageAdmin)
admin.site.register(Image, ImageAdmin)
5 changes: 4 additions & 1 deletion zubhub_backend/zubhub/activities/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@


class ActivitiesConfig(AppConfig):
name = 'activities'
name = "activities"

def ready(self):
import activities.signals # noqa: F401
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Generated by Django 3.2 on 2024-06-24 16:36

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("activities", "0017_alter_activity_materials_used"),
]

operations = [
migrations.AlterModelOptions(
name="activity",
options={"verbose_name_plural": "Activities"},
),
]
148 changes: 81 additions & 67 deletions zubhub_backend/zubhub/activities/models.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
import uuid
from django.db import models
from math import floor

from django.contrib.auth import get_user_model
from django.utils.text import slugify
from django.db import models
from django.utils import timezone
from math import floor
from projects.models import Category
from django.utils.text import slugify

Creator = get_user_model()


# TODO: use a single model for images everywhere
class Image(models.Model):
file_url = models.URLField(max_length=1000)
public_id = models.TextField(max_length=1000, blank=True)

def __str__(self):
try:
image = self.file_url
file_url = self.file_url
except AttributeError:
image = ''
return "Photo <%s:%s>" % (self.public_id, image)
file_url = ""
return "Photo <%s:%s>" % (self.public_id, file_url)


class InspiringArtist(models.Model):
'''this should be having more fields to distinguish an artist '''
image = models.ForeignKey(Image,
on_delete=models.CASCADE,
null=True,
blank=True)
"""this should be having more fields to distinguish an artist"""

image = models.ForeignKey(
Image, on_delete=models.CASCADE, null=True, blank=True
) # TODO: change to OneToOneField
short_biography = models.TextField(max_length=10000, blank=True, null=True)
name = models.CharField(max_length=100, null=True)

Expand All @@ -35,41 +36,45 @@ def __str__(self):


class Activity(models.Model):
id = models.UUIDField(primary_key=True,
default=uuid.uuid4,
editable=False,
unique=True)
creators = models.ManyToManyField(Creator,
related_name="activities_created")
id = models.UUIDField(
primary_key=True, default=uuid.uuid4, editable=False, unique=True
)
creators = models.ManyToManyField(Creator, related_name="activities_created")
title = models.CharField(max_length=500)
category = models.ManyToManyField("projects.Category",blank=True, related_name="activities")
introduction = models.CharField(max_length=10000,blank=True)
category = models.ManyToManyField(
"projects.Category", blank=True, related_name="activities"
)
introduction = models.CharField(max_length=10000, blank=True)
class_grade = models.CharField(max_length=50, blank=True)

learning_goals = models.TextField(max_length=10000, blank=True, null=True)
facilitation_tips = models.TextField(max_length=10000, blank=True, null=True)
motivation = models.TextField(max_length=10000, blank=True, null=True)
video = models.URLField(max_length=1000, blank=True, null=True)
materials_used = models.TextField(max_length=5000, blank=True, null=True)
materials_used_image = models.ForeignKey(Image,
on_delete=models.SET_NULL,
null=True,
blank=True,
)
inspiring_artist = models.ForeignKey(InspiringArtist,
on_delete=models.SET_NULL,
null=True,
related_name="inspiring_artist_activities",
blank=True,
)
views = models.ManyToManyField(Creator,
blank=True,
related_name="activities_viewed")
materials_used_image = models.ForeignKey( # TODO: change to OneToOneField
Image,
on_delete=models.SET_NULL,
null=True,
blank=True,
)
inspiring_artist = (
models.ForeignKey( # TODO: sure an activity can only be inspired by one artist?
InspiringArtist,
on_delete=models.SET_NULL,
null=True,
related_name="activities_inspired",
blank=True,
)
)
views = models.ManyToManyField(
Creator, blank=True, related_name="activities_viewed"
)
views_count = models.IntegerField(blank=True, default=0)
saved_count = models.IntegerField(blank=True, default=0)
saved_by = models.ManyToManyField(Creator,
blank=True,
related_name="activities_saved")
saved_by = models.ManyToManyField(
Creator, blank=True, related_name="activities_saved"
)
created_on = models.DateTimeField(default=timezone.now, null=True)
publish = models.BooleanField(default=False, null=True)
slug = models.SlugField(unique=True, max_length=1000)
Expand All @@ -79,56 +84,65 @@ def save(self, *args, **kwargs):
pass
else:
uid = str(uuid.uuid4())
uid = uid[0:floor(len(uid) / 6)]
uid = uid[0 : floor(len(uid) / 6)]
self.slug = slugify(self.title) + "-" + uid

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

def __str__(self):
return self.title

class Meta:
verbose_name_plural = "Activities"


class InspiringExample(models.Model):
activity = models.ForeignKey(Activity,
on_delete=models.CASCADE,
null=True,
related_name="inspiring_examples",
blank=True)
activity = models.ForeignKey(
Activity,
on_delete=models.CASCADE,
null=True,
related_name="inspiring_examples",
blank=True,
)
description = models.TextField(max_length=10000, blank=True)
credit = models.TextField(max_length=1000, blank=True)
image = models.ForeignKey(Image,
on_delete=models.CASCADE,
null=True,
blank=True)
image = models.ForeignKey(
Image, on_delete=models.CASCADE, null=True, blank=True
) # TODO: change to OneToOneField

def __str__(self):
return self.image
return self.image.file_url


class ActivityImage(models.Model):
activity = models.ForeignKey(Activity,
on_delete=models.CASCADE,
null=True,
related_name="activity_images",
blank=True)
image = models.ForeignKey(Image,
on_delete=models.CASCADE,
null=True,
blank=True)
activity = models.ForeignKey(
Activity,
on_delete=models.CASCADE,
null=True,
related_name="activity_images",
blank=True,
)
image = models.ForeignKey(
Image, on_delete=models.CASCADE, null=True, blank=True
) # TODO: change to OneToOneField

def __str__(self):
return self.image
return self.image.file_url


class ActivityMakingStep(models.Model):
activity = models.ForeignKey(Activity,
on_delete=models.CASCADE,
null=True,
related_name="making_steps",
blank=True)

title = models.TextField(max_length=500,null=True)
image = models.ManyToManyField(Image,blank=True)
activity = models.ForeignKey(
Activity,
on_delete=models.CASCADE,
null=True,
related_name="making_steps",
blank=True,
)

title = models.TextField(max_length=500, null=True)
image = models.ManyToManyField(
Image, blank=True
) # TODO: should this be ManyToManyField or OneToOneField ?
description = models.TextField(max_length=10000, blank=True)
step_order = models.IntegerField()

Expand Down
Loading

0 comments on commit e07229b

Please sign in to comment.