Skip to content

Commit

Permalink
chore(fix): Added manytomany relationship to Categories schema
Browse files Browse the repository at this point in the history
  • Loading branch information
happychuks committed Aug 14, 2024
1 parent 4c88da1 commit ba86849
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 15 deletions.
22 changes: 14 additions & 8 deletions server/apps/research/admin/article_admin.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
from django.contrib import admin
from django import forms
from django_ckeditor_5.widgets import CKEditor5Widget
from apps.research.models import Article, Author
from apps.research.models import Article, Author, Category

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
"""Admin interface for the Article model."""

fieldsets = [
('Article Details', {'fields': ['title', 'category', 'thumb', 'content', 'summary', 'status', 'authors']}),
('Article Details', {'fields': ['title', 'categories', 'thumb', 'content', 'summary', 'status', 'authors']}),
]
list_display = ('title', 'display_authors', 'status', 'views', 'category', 'created_at')
list_display = ('title', 'display_authors', 'status', 'views', 'display_categories', 'created_at')
search_fields = ('title', 'authors__user__username', 'authors__twitter_username', 'content')
list_per_page = 25
list_filter = ('authors', 'status', 'category', 'created_at')
list_per_page = 25
list_filter = ('authors', 'status', 'categories', 'created_at')
readonly_fields = ('views', 'slug')
list_editable = ('status',)

Expand All @@ -29,17 +29,23 @@ def display_authors(self, obj):
return ", ".join(author.user.username for author in obj.authors.all())
display_authors.short_description = 'Authors'

def display_categories(self, obj):
"""Return a comma-separated list of categories for the article."""
return ", ".join(category.name for category in obj.categories.all())
display_categories.short_description = 'Categories'

def save_model(self, request, obj, form, change):
"""Automatically add the logged-in user as the author when creating a new article."""
if not change: # If creating a new article
author = Author.objects.filter(user=request.user).first() # Get the Author instance for the logged-in user
author = Author.objects.filter(user=request.user).first()
if author:
obj.save()
obj.authors.add(author)
super().save_model(request, obj, form, change)
else:
super().save_model(request, obj, form, change)

def has_change_permission(self, request, obj=None):
"""Check if the user has permission to change the article."""

if request.user.is_superuser:
return True
if not super().has_change_permission(request, obj):
Expand Down
2 changes: 2 additions & 0 deletions server/apps/research/admin/category_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ class CategoryAdmin(admin.ModelAdmin):
list_display = ('name', 'created_at')
list_per_page = 25
search_fields = ('name',)
list_filter = ('created_at',)
ordering = ('name',)
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 5.0.7 on 2024-08-14 09:53

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('research', '0005_alter_author_bio_alter_author_twitter_username'),
]

operations = [
migrations.RemoveField(
model_name='article',
name='category',
),
migrations.AddField(
model_name='article',
name='categories',
field=models.ManyToManyField(blank=True, related_name='articles', to='research.category'),
),
migrations.AlterField(
model_name='article',
name='summary',
field=models.CharField(blank=True, max_length=100),
),
]
4 changes: 2 additions & 2 deletions server/apps/research/models/article.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ class Article(BaseModel):

title = models.CharField(max_length=100)
content = CKEditor5Field(null=True, blank=True, config_name='extends')
summary = models.TextField(blank=True)
summary = models.CharField(max_length=100, blank=True)
authors = models.ManyToManyField(Author, blank=True, related_name='articles')
slug = models.SlugField(blank=True)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, related_name="articles")
categories = models.ManyToManyField(Category, blank=True, related_name='articles')
thumb = models.ImageField(upload_to='images/', default='../media/images/2077-Collective.png', blank=True)
views = models.PositiveBigIntegerField(default=0)
status = models.CharField(max_length=10, choices=options, default='draft')
Expand Down
25 changes: 20 additions & 5 deletions server/apps/research/serializers/article_serializer.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from rest_framework import serializers
from ..models import Article, Author
from ..models import Article, Author, Category
from .author_serializer import AuthorSerializer
from .category_serializer import CategorySerializer

class ArticleSerializer(serializers.ModelSerializer):
"""Serializer for the Article model."""
authors = AuthorSerializer(many=True, read_only=True)
slug = serializers.ReadOnlyField()
category = CategorySerializer()
categories = CategorySerializer(many=True)
slug = serializers.ReadOnlyField()
views = serializers.ReadOnlyField()

class Meta:
Expand All @@ -17,27 +17,42 @@ class Meta:
class ArticleCreateUpdateSerializer(serializers.ModelSerializer):
"""Serializer for creating and updating articles."""
authors = serializers.PrimaryKeyRelatedField(queryset=Author.objects.all(), many=True, required=False)
categories = serializers.PrimaryKeyRelatedField(queryset=Category.objects.all(), many=True, required=False)

class Meta:
model = Article
fields = ['title', 'category', 'thumb', 'content', 'summary', 'status', 'authors']
fields = ['title', 'categories', 'thumb', 'content', 'summary', 'status', 'authors']

# TODO : Debug this method to add the logged-in user as the author when creating a new article
def create(self, validated_data):
request = self.context.get('request')
authors = validated_data.pop('authors', [])
categories = validated_data.pop('categories', [])

if not authors and request and hasattr(request, 'user'):
user_author = Author.objects.filter(user=request.user).first()
if user_author:
authors = [user_author]

article = Article.objects.create(**validated_data)

if authors:
article.authors.set(authors)
if categories:
article.categories.set(categories)

return article


def update(self, instance, validated_data):
authors = validated_data.pop('authors', [])
categories = validated_data.pop('categories', [])

instance = super().update(instance, validated_data)

if authors:
instance.authors.set(authors) # Update authors for the article
instance.authors.set(authors)
if categories:
instance.categories.set(categories)

return instance
1 change: 1 addition & 0 deletions server/core/config/ckeditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
'bulletedList', 'numberedList', 'findAndReplace', 'highlight', 'subscript', 'superscript',
'specialCharacters', '|', 'imageInsert', 'code', 'codeBlock', 'insertTable', 'mediaEmbed', '|',
'blockQuote', 'fullscreen', 'removeFormat'],
'extraAllowedContent': '*(*);*[*]',

'image': {
'toolbar': ['imageTextAlternative', '|', 'imageStyle:alignLeft',
Expand Down
Binary file modified server/db.sqlite3
Binary file not shown.
Binary file not shown.

0 comments on commit ba86849

Please sign in to comment.