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.
 
 

156 lines
5.1 KiB

from django.contrib import admin
from django.utils.translation import gettext_lazy as _
from unfold.admin import ModelAdmin, TabularInline
from unfold.decorators import display
# Import your custom admin site
from utils.admin import project_admin_site
# Import your models
from ..models import (
BookReference,
BookReferenceImage,
BookAuthor,
BookAttribute
)
# -----------------------------------------------------------------------------
# 1. Inlines
# -----------------------------------------------------------------------------
class BookReferenceImageInline(TabularInline):
"""
Inline for managing Book Images directly inside the BookReference page.
"""
model = BookReferenceImage
extra = 0
fields = ('image', 'order', 'description')
readonly_fields = ('created_at',)
class BookAttributeInline(TabularInline):
"""
Inline for managing Book Attributes (Key-Value pairs) inside BookReference.
"""
model = BookAttribute
extra = 0
fields = ('title', 'value')
readonly_fields = ('created_at',)
# -----------------------------------------------------------------------------
# 2. Main Admins
# -----------------------------------------------------------------------------
class BookReferenceAdmin(ModelAdmin):
"""Admin for BookReference model"""
# Use custom methods for JSON fields to show readable text
list_display = (
'get_title_display',
'slug',
'get_publisher_display',
'year_of_publication',
'rate',
'created_at'
)
list_filter = ('year_of_publication', 'rate', 'created_at')
# Searching by JSON fields via string is limited in Django,
# so we focus on standard fields
search_fields = ('isbn', 'slug', 'volume')
readonly_fields = ('created_at', 'updated_at')
# Add the inlines to manage images and attributes on the same page
inlines = [BookReferenceImageInline, BookAttributeInline]
fieldsets = (
(_('Basic Info'), {
'fields': ('title', 'description', 'slug', 'language')
}),
(_('Publication Info'), {
'fields': ('publisher', 'isbn', 'year_of_publication', 'number_page', 'volume')
}),
(_('Rating & Stats'), {
'fields': ('rate', 'created_at', 'updated_at')
}),
)
# --- Custom Display Methods ---
@display(description=_('Title'), ordering='title')
def get_title_display(self, obj):
return self._extract_first_text(obj.title)
@display(description=_('Publisher'))
def get_publisher_display(self, obj):
return self._extract_first_text(obj.publisher)
def _extract_first_text(self, json_data):
"""Helper to safely extract the first 'text' from a JSON list"""
if json_data and isinstance(json_data, list) and len(json_data) > 0:
first_item = json_data[0]
if isinstance(first_item, dict):
return first_item.get('text', '-')
return '-'
class BookAuthorAdmin(ModelAdmin):
"""Admin for BookAuthor model"""
list_display = ('get_name_display', 'created_at', 'updated_at')
search_fields = ('name',) # Note: Search works best on exact text matches
readonly_fields = ('created_at', 'updated_at')
# Use filter_horizontal for ManyToMany fields to make selection easier
filter_horizontal = ('book_references',)
@display(description=_('Name'), ordering='name')
def get_name_display(self, obj):
if obj.name and isinstance(obj.name, list) and len(obj.name) > 0:
first = obj.name[0]
if isinstance(first, dict):
return first.get('text', '-')
return '-'
class BookAttributeAdmin(ModelAdmin):
"""
Admin for managing Attributes independently.
Useful if you want to see all attributes across all books.
"""
list_display = ('get_title_display', 'get_value_display', 'get_book_display', 'created_at')
list_filter = ('created_at',)
search_fields = ('book_reference__slug',)
@display(description=_('Title'), ordering='title')
def get_title_display(self, obj):
return self._extract_first_text(obj.title)
@display(description=_('Value'), ordering='value')
def get_value_display(self, obj):
return self._extract_first_text(obj.value)
@display(description=_('Book Reference'), ordering='book_reference')
def get_book_display(self, obj):
if obj.book_reference:
return self._extract_first_text(obj.book_reference.title)
return '-'
def _extract_first_text(self, json_data):
if json_data and isinstance(json_data, list) and len(json_data) > 0:
first = json_data[0]
if isinstance(first, dict):
return first.get('text', '-')
return '-'
# -----------------------------------------------------------------------------
# 3. Registration
# -----------------------------------------------------------------------------
project_admin_site.register(BookReference, BookReferenceAdmin)
project_admin_site.register(BookAuthor, BookAuthorAdmin)
project_admin_site.register(BookAttribute, BookAttributeAdmin)