-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(fix): Refactored the server codebase with updated model schema
- Loading branch information
1 parent
636558c
commit 4c88da1
Showing
26 changed files
with
396 additions
and
164 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,77 +1,11 @@ | ||
from django.contrib import admin | ||
from django import forms | ||
from django_ckeditor_5.widgets import CKEditor5Widget | ||
from apps.research.models import Article, Category | ||
|
||
# Import admin classes from separate files | ||
from .admin.category_admin import CategoryAdmin | ||
from .admin.author_admin import AuthorAdmin | ||
from .admin.article_admin import ArticleAdmin | ||
|
||
@admin.register(Category) | ||
class CategoryAdmin(admin.ModelAdmin): | ||
list_display = ('name', 'created_at') | ||
|
||
list_per_page = 25 | ||
|
||
search_fields = ('name',) | ||
|
||
|
||
# Override Django Admin config with CK Editor | ||
@admin.register(Article) | ||
class ArticleAdmin(admin.ModelAdmin): | ||
# Order in which fields are displayed in the admin panel | ||
fieldsets = [ | ||
( | ||
'2077 Collective Articles', { | ||
'fields': [ | ||
'title', | ||
'category', | ||
'thumb', | ||
'content', | ||
'summary', | ||
'status', | ||
], | ||
} | ||
), | ||
] | ||
|
||
def get_form(self, request, obj=None, **kwargs): | ||
form = super().get_form(request, obj, **kwargs) | ||
form.base_fields['content'].widget = CKEditor5Widget(attrs={"class": "django_ckeditor_5"}) | ||
return form | ||
|
||
list_display = ('title', 'author', 'status', 'views', 'category', 'created_at') | ||
|
||
search_fields = ('title', 'content', 'author__username') | ||
# Number of articles per page | ||
list_per_page = 25 | ||
|
||
# Add filters to the right side of the admin panel | ||
list_filter = ('author', 'status', 'category', 'created_at') | ||
|
||
# Make 'views' read-only | ||
readonly_fields = ('views', 'author', 'slug') | ||
|
||
# Make fields 'editable' | ||
list_editable = ['status'] | ||
|
||
# Override save_model to automatically set author to the logged-in user when creating a new article | ||
def save_model(self, request, obj, form, change): | ||
if not change: | ||
obj.author = request.user | ||
super().save_model(request, obj, form, change) | ||
|
||
# Override has_change_permission to restrict editing to the author only | ||
def has_change_permission(self, request, obj=None): | ||
has_class_permission = super().has_change_permission(request, obj) | ||
if not has_class_permission: | ||
return False | ||
if obj is not None and obj.author != request.user: | ||
return False | ||
return True | ||
|
||
# Override has_delete_permission to restrict deleting to the author only | ||
def has_delete_permission(self, request, obj=None): | ||
has_class_permission = super().has_delete_permission(request, obj) | ||
if not has_class_permission: | ||
return False | ||
if obj is not None and obj.author != request.user: | ||
return False | ||
return True | ||
# Register admin classes | ||
admin.site.register(CategoryAdmin) | ||
admin.site.register(AuthorAdmin) | ||
admin.site.register(ArticleAdmin) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from .category_admin import CategoryAdmin | ||
from .author_admin import AuthorAdmin | ||
from .article_admin import ArticleAdmin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
from django.contrib import admin | ||
from django import forms | ||
from django_ckeditor_5.widgets import CKEditor5Widget | ||
from apps.research.models import Article, Author | ||
|
||
@admin.register(Article) | ||
class ArticleAdmin(admin.ModelAdmin): | ||
"""Admin interface for the Article model.""" | ||
|
||
fieldsets = [ | ||
('Article Details', {'fields': ['title', 'category', 'thumb', 'content', 'summary', 'status', 'authors']}), | ||
] | ||
list_display = ('title', 'display_authors', 'status', 'views', 'category', 'created_at') | ||
search_fields = ('title', 'authors__user__username', 'authors__twitter_username', 'content') | ||
list_per_page = 25 | ||
list_filter = ('authors', 'status', 'category', 'created_at') | ||
readonly_fields = ('views', 'slug') | ||
list_editable = ('status',) | ||
|
||
def get_form(self, request, obj=None, **kwargs): | ||
"""Return a form with CKEditor5Widget for the content field.""" | ||
form = super().get_form(request, obj, **kwargs) | ||
if 'content' in form.base_fields: | ||
form.base_fields['content'].widget = CKEditor5Widget(attrs={"class": "django_ckeditor_5"}) | ||
return form | ||
|
||
def display_authors(self, obj): | ||
"""Return a comma-separated list of authors for the article.""" | ||
return ", ".join(author.user.username for author in obj.authors.all()) | ||
display_authors.short_description = 'Authors' | ||
|
||
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 | ||
if author: | ||
obj.authors.add(author) | ||
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): | ||
return False | ||
if obj is not None and not obj.authors.filter(user=request.user).exists(): | ||
return False | ||
return True | ||
|
||
def has_delete_permission(self, request, obj=None): | ||
"""Check if the user has permission to delete the article.""" | ||
if request.user.is_superuser: | ||
return True | ||
if not super().has_delete_permission(request, obj): | ||
return False | ||
if obj is not None and not obj.authors.filter(user=request.user).exists(): | ||
return False | ||
return True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from django.contrib import admin | ||
from apps.research.models import Author | ||
|
||
@admin.register(Author) | ||
class AuthorAdmin(admin.ModelAdmin): | ||
"""Admin interface for the Author model.""" | ||
|
||
fieldsets = [ | ||
('Author Details', {'fields': ['user', 'bio', 'twitter_username']}), | ||
] | ||
list_display = ('user', 'bio', 'twitter_username') | ||
list_per_page = 25 | ||
search_fields = ('user__username', 'twitter_username') | ||
|
||
def save_model(self, request, obj, form, change): | ||
"""Automatically set the author to the logged-in user when creating a new author.""" | ||
if not change: # If creating a new author | ||
obj.user = request.user | ||
super().save_model(request, obj, form, change) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from django.contrib import admin | ||
from apps.research.models import Category | ||
|
||
@admin.register(Category) | ||
class CategoryAdmin(admin.ModelAdmin): | ||
"""Admin interface for the Category model.""" | ||
|
||
list_display = ('name', 'created_at') | ||
list_per_page = 25 | ||
search_fields = ('name',) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
server/apps/research/migrations/0003_remove_article_author_author_article_authors.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# Generated by Django 5.0.7 on 2024-08-14 01:46 | ||
|
||
import django.db.models.deletion | ||
import uuid | ||
from django.conf import settings | ||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('research', '0002_initial'), | ||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), | ||
] | ||
|
||
operations = [ | ||
migrations.RemoveField( | ||
model_name='article', | ||
name='author', | ||
), | ||
migrations.CreateModel( | ||
name='Author', | ||
fields=[ | ||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)), | ||
('created_at', models.DateTimeField(auto_now_add=True, db_index=True)), | ||
('updated_at', models.DateTimeField(auto_now=True, null=True)), | ||
('bio', models.TextField(blank=True)), | ||
('twitter_username', models.CharField(blank=True, max_length=255)), | ||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), | ||
], | ||
options={ | ||
'verbose_name_plural': 'Author(s)', | ||
}, | ||
), | ||
migrations.AddField( | ||
model_name='article', | ||
name='authors', | ||
field=models.ManyToManyField(blank=True, related_name='articles', to='research.author'), | ||
), | ||
] |
17 changes: 17 additions & 0 deletions
17
server/apps/research/migrations/0004_alter_author_options.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Generated by Django 5.0.7 on 2024-08-14 02:47 | ||
|
||
from django.db import migrations | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('research', '0003_remove_article_author_author_article_authors'), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterModelOptions( | ||
name='author', | ||
options={'verbose_name_plural': 'Authors'}, | ||
), | ||
] |
23 changes: 23 additions & 0 deletions
23
server/apps/research/migrations/0005_alter_author_bio_alter_author_twitter_username.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Generated by Django 5.0.7 on 2024-08-14 06:45 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('research', '0004_alter_author_options'), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterField( | ||
model_name='author', | ||
name='bio', | ||
field=models.TextField(blank=True, null=True), | ||
), | ||
migrations.AlterField( | ||
model_name='author', | ||
name='twitter_username', | ||
field=models.CharField(blank=True, max_length=100, null=True), | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,7 @@ | ||
from django.contrib.auth.models import User | ||
from django.db import models | ||
from django.utils.text import slugify | ||
from django_ckeditor_5.fields import CKEditor5Field | ||
# apps/research/models.py | ||
|
||
from apps.common.models import BaseModel | ||
from apps.research.managers import ArticleObjects | ||
from .category import Category | ||
from .author import Author | ||
from .article import Article | ||
|
||
|
||
class Category(BaseModel): | ||
name = models.CharField(max_length=255) | ||
|
||
class Meta: | ||
verbose_name_plural = 'Categories' | ||
|
||
def __str__(self): | ||
return self.name | ||
|
||
|
||
class Article(BaseModel): | ||
options = ( | ||
('draft', 'Draft'), | ||
('ready', 'Ready'), | ||
) | ||
|
||
title = models.CharField(max_length=100) | ||
content = CKEditor5Field(null=True, blank=True, config_name='extends') | ||
summary = models.TextField(blank=True) | ||
author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True) | ||
slug = models.SlugField(blank=True) | ||
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=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') | ||
objects = models.Manager() | ||
post_objects = ArticleObjects() | ||
|
||
class Meta: | ||
ordering = ('-created_at',) | ||
|
||
def __str__(self): | ||
return self.title | ||
|
||
def save(self, *args, **kwargs): | ||
if not self.slug: | ||
self.slug = self.generate_unique_slug() | ||
super().save(*args, **kwargs) | ||
|
||
def generate_unique_slug(self): | ||
base_slug = slugify(self.title) | ||
slug = base_slug | ||
num = 1 | ||
while Article.objects.filter(slug=slug).exists(): | ||
slug = f"{base_slug}-{num}" | ||
num += 1 | ||
return slug | ||
__all__ = ['Category', 'Author', 'Article'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from .category import Category | ||
from .author import Author | ||
from .article import Article |
Oops, something went wrong.