You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

192 lines
7.0 KiB

from django.contrib import admin
from django.utils.translation import gettext_lazy as _
from django.urls import reverse
from django.utils.html import format_html
from ajaxdatatable.admin import AjaxDatatable
from apps.library.models import *
@admin.register(Book)
class BookAdmin(AjaxDatatable):
list_display = ('title', 'slug', 'status', 'pin', 'file_type', 'view_count', 'created_at')
list_filter = ('status', 'pin', 'file_type', 'created_at', 'updated_at')
search_fields = ('title', 'slug', 'summary', 'description')
# autocomplete_fields = ('categories', 'collections', )
fieldsets = (
(None, {
'fields': ('title', 'slug', 'summary', 'description', 'thumbnail', 'pages_count')
}),
(_('Status'), {
'fields': ('status', 'pin')
}),
(_('File Information'), {
'fields': ('file_type', 'book_file')
}),
(_('Relations'), {
'fields': ('categories', 'collections')
}),
(_('Statistics'), {
'fields': ('view_count',)
}),
)
class BookCollectionAdminBase(AjaxDatatable):
"""Base admin class for all book collection types"""
list_display = ('get_title', 'status', 'order', 'count_books')
list_filter = ('status',)
search_fields = ('title',)
autocomplete_fields = ('books',)
ordering = ('order',)
fieldsets = (
(None, {
'fields': ('title', 'summary', 'status', 'order')
}),
(_('Books'), {
'fields': ('books',)
}),
)
exclude = ('display_position',)
def get_title(self, obj):
return str(obj.title)
get_title.short_description = _('Title')
@admin.display(description=_('Number of Books'))
def count_books(self, obj):
count = obj.books.count()
if count > 0:
url = reverse('admin:library_book_changelist') + f'?collections__id__exact={obj.id}'
return format_html('<a href="{}">{}</a>', url, count)
return count
@admin.register(PinnedBookCollection)
class PinnedBookCollectionAdmin(BookCollectionAdminBase):
"""Admin for pinned book collections only"""
def get_queryset(self, request):
# Only show pinned collections
return super().get_queryset(request).filter(display_position=BookCollection.DisplayPosition.PINNED)
def save_model(self, request, obj, form, change):
# Ensure the display_position is always set to PINNED
obj.display_position = BookCollection.DisplayPosition.PINNED
super().save_model(request, obj, form, change)
@admin.register(MiddleBookCollection)
class MiddleBookCollectionAdmin(BookCollectionAdminBase):
"""Admin for middle section book collections only"""
def get_queryset(self, request):
# Only show middle section collections
return super().get_queryset(request).filter(display_position=BookCollection.DisplayPosition.MIDDLE)
def has_add_permission(self, request):
# Check if a middle collection already exists
exists = BookCollection.objects.filter(display_position=BookCollection.DisplayPosition.MIDDLE).exists()
# Only allow adding if no middle collection exists
return not exists
def has_delete_permission(self, request, obj=None):
# Prevent deletion of the middle collection
return False
def save_model(self, request, obj, form, change):
# Ensure the display_position is always set to MIDDLE
obj.display_position = BookCollection.DisplayPosition.MIDDLE
super().save_model(request, obj, form, change)
def changelist_view(self, request, extra_context=None):
# Check if a middle collection exists
try:
# Try to get the first (and should be only) middle collection
obj = self.get_queryset(request).first()
if obj:
# If it exists, redirect to the change view for this object
from django.http import HttpResponseRedirect
from django.urls import reverse
url = reverse(
'admin:%s_%s_change' % (obj._meta.app_label, obj._meta.model_name),
args=[obj.pk]
)
return HttpResponseRedirect(url)
except Exception:
# If any error occurs, just show the changelist view as usual
pass
# If no object exists or there was an error, show the default changelist view
return super().changelist_view(request, extra_context)
@admin.register(BottomBookCollection)
class BottomBookCollectionAdmin(BookCollectionAdminBase):
"""Admin for bottom section book collections only"""
def get_queryset(self, request):
# Only show bottom section collections
return super().get_queryset(request).filter(display_position=BookCollection.DisplayPosition.BOTTOM)
def has_add_permission(self, request):
# Check if a bottom collection already exists
exists = BookCollection.objects.filter(display_position=BookCollection.DisplayPosition.BOTTOM).exists()
# Only allow adding if no bottom collection exists
return not exists
def has_delete_permission(self, request, obj=None):
# Prevent deletion of the bottom collection
return False
def save_model(self, request, obj, form, change):
# Ensure the display_position is always set to BOTTOM
obj.display_position = BookCollection.DisplayPosition.BOTTOM
super().save_model(request, obj, form, change)
def changelist_view(self, request, extra_context=None):
# Check if a bottom collection exists
try:
# Try to get the first (and should be only) bottom collection
obj = self.get_queryset(request).first()
if obj:
# If it exists, redirect to the change view for this object
from django.http import HttpResponseRedirect
from django.urls import reverse
url = reverse(
'admin:%s_%s_change' % (obj._meta.app_label, obj._meta.model_name),
args=[obj.pk]
)
return HttpResponseRedirect(url)
except Exception:
# If any error occurs, just show the changelist view as usual
pass
# If no object exists or there was an error, show the default changelist view
return super().changelist_view(request, extra_context)
@admin.register(Category)
class CategoryAdmin(AjaxDatatable):
list_display = ('title', 'slug', 'status', 'count_books', 'created_at')
list_filter = ('status', 'created_at', 'updated_at')
search_fields = ('title', 'slug')
autocomplete_fields = ('books',)
@admin.display(description=_('Number of Books'))
def count_books(self, obj):
count = obj.books.count()
if count > 0:
url = reverse('admin:library_book_changelist') + f'?categories__id__exact={obj.id}'
return format_html('<a href="{}">{}</a>', url, count)
return count