Files

216 lines
8.7 KiB
Python

from django import forms
from django.contrib import admin
from import_export.admin import ImportExportModelAdmin
from simplemde.widgets import SimpleMDEEditor
from apps.blog.models import BlogBanner, Category, Tag, Post, PostAsset, Comment, Like, SavedPost
from apps.blog.resources import PostResource, CategoryResource
from core.admin import SoftDeleteListFilter, BaseModelAdmin
@admin.register(Category)
class CategoryAdmin(BaseModelAdmin, ImportExportModelAdmin):
resource_class = CategoryResource
list_display = ('name', 'parent', 'slug', 'created_at', 'is_deleted')
list_filter = ('created_at', 'is_deleted', SoftDeleteListFilter)
search_fields = ('name', 'description', 'parent__name')
prepopulated_fields = {'slug': ('name',)}
readonly_fields = ('created_at', 'updated_at', 'deleted_at')
fieldsets = (
('Content', {
'fields': ('name', 'parent', 'slug', 'description')
}),
('Metadata', {
'fields': ('created_at', 'updated_at')
}),
('Soft Delete', {
'fields': ('is_deleted', 'deleted_at'),
'classes': ('collapse',)
})
)
actions = BaseModelAdmin.actions + ['restore_categories']
def restore_categories(self, request, queryset):
for category in queryset:
category.restore()
self.message_user(request, f"Restored {queryset.count()} categories.")
restore_categories.short_description = "Restore selected categories"
@admin.register(Tag)
class TagAdmin(BaseModelAdmin, ImportExportModelAdmin):
list_display = ('name', 'slug', 'created_at', 'is_deleted')
list_filter = ('created_at', 'is_deleted', SoftDeleteListFilter)
search_fields = ('name',)
prepopulated_fields = {'slug': ('name',)}
readonly_fields = ('created_at', 'updated_at', 'deleted_at')
fieldsets = (
('Content', {
'fields': ('name', 'slug')
}),
('Metadata', {
'fields': ('created_at', 'updated_at')
}),
('Soft Delete', {
'fields': ('is_deleted', 'deleted_at'),
'classes': ('collapse',)
})
)
class PostAdminForm(forms.ModelForm):
content = forms.CharField(widget=SimpleMDEEditor())
excerpt = forms.CharField(widget=SimpleMDEEditor())
class Meta:
model = Post
fields = '__all__'
@admin.register(Post)
class PostAdmin(BaseModelAdmin, ImportExportModelAdmin):
form = PostAdminForm
resource_class = PostResource
list_display = ('title', 'author', 'status', 'category', 'is_featured', 'submitted_at', 'published_at', 'created_at')
list_filter = ('status', 'is_featured', 'category', 'tags', 'created_at', 'published_at', SoftDeleteListFilter)
search_fields = ('title', 'content', 'author__username')
prepopulated_fields = {'slug': ('title',)}
filter_horizontal = ('tags', 'writers')
date_hierarchy = 'published_at'
fieldsets = (
('Content', {
'fields': ('title', 'slug', 'content', 'excerpt', 'featured_image')
}),
('SEO', {
'fields': ('seo_title', 'seo_description', 'canonical_url', 'og_title', 'og_description', 'og_image', 'noindex', 'focus_keyword', 'reading_time')
}),
('Metadata', {
'fields': ('author', 'writers', 'category', 'tags', 'status', 'is_featured', 'submitted_at', 'reviewed_at', 'reviewed_by', 'review_note', 'published_at', 'published_by')
}),
('Soft Delete', {
'fields': ('is_deleted', 'deleted_at'),
'classes': ('collapse',)
}),
)
readonly_fields = ('deleted_at', 'content_html', 'reading_time')
actions = BaseModelAdmin.actions + ['submit_for_review', 'request_changes', 'make_published', 'make_draft', 'make_featured', 'restore_posts']
def submit_for_review(self, request, queryset):
queryset.update(status='submitted')
self.message_user(request, f"Submitted {queryset.count()} posts for review.")
submit_for_review.short_description = "Submit selected posts for review"
def request_changes(self, request, queryset):
queryset.update(status='changes_requested', reviewed_by=request.user)
self.message_user(request, f"Requested changes on {queryset.count()} posts.")
request_changes.short_description = "Request changes on selected posts"
def make_published(self, request, queryset):
queryset.update(status='published', published_by=request.user)
self.message_user(request, f"Published {queryset.count()} posts.")
make_published.short_description = "Mark selected posts as published"
def make_draft(self, request, queryset):
queryset.update(status='draft')
self.message_user(request, f"Marked {queryset.count()} posts as draft.")
make_draft.short_description = "Mark selected posts as draft"
def make_featured(self, request, queryset):
queryset.update(is_featured=True)
self.message_user(request, f"Featured {queryset.count()} posts.")
make_featured.short_description = "Mark selected posts as featured"
def restore_posts(self, request, queryset):
for post in queryset:
post.restore()
self.message_user(request, f"Restored {queryset.count()} posts.")
restore_posts.short_description = "Restore selected posts"
@admin.register(Comment)
class CommentAdmin(BaseModelAdmin):
list_display = ('author', 'post', 'content_preview', 'is_approved', 'is_hidden', 'is_deleted', 'created_at')
list_filter = ('is_approved', 'is_hidden', 'created_at', 'post', SoftDeleteListFilter)
search_fields = ('content', 'author__username', 'author__last_name', 'author__first_name', 'post__title')
readonly_fields = ('content_preview', 'created_at', 'updated_at', 'deleted_at')
fieldsets = (
('Content', {
'fields': ('post', 'author', 'content')
}),
('Metadata', {
'fields': ('is_approved', 'is_hidden', 'hidden_by', 'hidden_at', 'moderation_note', 'created_at', 'updated_at')
}),
('Soft Delete', {
'fields': ('is_deleted', 'deleted_at', 'deleted_by', 'delete_note'),
'classes': ('collapse',)
})
)
actions = BaseModelAdmin.actions + ['approve_comments', 'hide_comments', 'unhide_comments']
def content_preview(self, obj):
return obj.content[:50] + '...' if len(obj.content) > 50 else obj.content
content_preview.short_description = 'Content Preview'
def approve_comments(self, request, queryset):
queryset.update(is_approved=True, is_hidden=False, hidden_by=None, hidden_at=None, moderation_note='')
self.message_user(request, f"Approved {queryset.count()} comments.")
approve_comments.short_description = "Approve selected comments"
def hide_comments(self, request, queryset):
for comment in queryset:
comment.hide(request.user)
self.message_user(request, f"Hidden {queryset.count()} comments.")
hide_comments.short_description = "Hide selected comments"
def unhide_comments(self, request, queryset):
for comment in queryset:
comment.unhide()
self.message_user(request, f"Restored {queryset.count()} comments.")
unhide_comments.short_description = "Unhide selected comments"
@admin.register(Like)
class LikeAdmin(admin.ModelAdmin):
list_display = ('user', 'post', 'created_at')
list_filter = ('created_at', 'post')
search_fields = ('user__username', 'post__title')
@admin.register(SavedPost)
class SavedPostAdmin(admin.ModelAdmin):
list_display = ('user', 'post', 'created_at')
list_filter = ('created_at', 'post')
search_fields = ('user__username', 'post__title')
@admin.register(PostAsset)
class PostAssetAdmin(BaseModelAdmin):
list_display = ('title', 'post', 'file_type', 'mime_type', 'size', 'uploaded_by', 'created_at')
list_filter = ('file_type', 'mime_type', 'created_at')
search_fields = ('title', 'caption', 'alt_text', 'post__title', 'uploaded_by__username')
readonly_fields = ('size', 'mime_type', 'created_at', 'updated_at', 'deleted_at')
@admin.register(BlogBanner)
class BlogBannerAdmin(BaseModelAdmin):
list_display = ('title', 'url', 'is_active', 'sort_order', 'created_at', 'is_deleted')
list_filter = ('is_active', 'created_at', 'is_deleted', SoftDeleteListFilter)
search_fields = ('title', 'alt_text', 'url')
readonly_fields = ('created_at', 'updated_at', 'deleted_at')
fieldsets = (
('Banner', {
'fields': ('title', 'alt_text', 'image', 'url', 'is_active', 'sort_order')
}),
('Metadata', {
'fields': ('created_at', 'updated_at')
}),
('Soft Delete', {
'fields': ('is_deleted', 'deleted_at'),
'classes': ('collapse',)
}),
)