Files
mwy/backend/journal/admin.py
flower_linux 6cc3fdf411 mwy2.0
2026-05-20 16:31:07 +08:00

192 lines
5.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from django.contrib import admin
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from .models import Config, Guestbook, Memory, MemoryPhoto
class JournalStaffAccessMixin:
"""
手账站点多为小项目:凡 is_staff 即可在后台增删改查(无需在「用户」里逐项勾选 journal.* 权限)。
生产环境若需细分权限,可移除此 Mixin 并改回 Django 默认的 has_perm 校验。
"""
def has_module_permission(self, request):
u = request.user
return bool(getattr(u, "is_active", False) and getattr(u, "is_staff", False))
def has_view_permission(self, request, obj=None):
u = request.user
return bool(getattr(u, "is_active", False) and getattr(u, "is_staff", False))
def has_change_permission(self, request, obj=None):
u = request.user
return bool(getattr(u, "is_active", False) and getattr(u, "is_staff", False))
def has_add_permission(self, request):
u = request.user
return bool(getattr(u, "is_active", False) and getattr(u, "is_staff", False))
def has_delete_permission(self, request, obj=None):
u = request.user
return bool(getattr(u, "is_active", False) and getattr(u, "is_staff", False))
class MemoryPhotoInline(admin.TabularInline):
model = MemoryPhoto
extra = 1
fields = ("image", "sort_order")
@admin.register(Memory)
class MemoryAdmin(JournalStaffAccessMixin, admin.ModelAdmin):
inlines = (MemoryPhotoInline,)
list_display = (
"event_title",
"story_order",
"date",
"unique_feature_type",
"nepal_art_style",
"is_finale",
"thumb_preview",
)
list_display_links = ("event_title",)
list_filter = ("unique_feature_type", "nepal_art_style", "is_finale", "date")
list_editable = ("story_order",)
search_fields = ("event_title", "main_text")
readonly_fields = ("image_preview",)
ordering = ("story_order", "id")
fieldsets = (
(
"叙事",
{
"fields": (
"story_order",
"date",
"event_title",
"is_finale",
)
},
),
(
"版式",
{
"fields": (
"unique_feature_type",
"nepal_art_style",
"image",
"image_preview",
"main_text",
)
},
),
)
@admin.display(description="缩略图")
def thumb_preview(self, obj: Memory) -> str:
url = None
if obj.image:
url = obj.image.url
else:
first = obj.photos.order_by("sort_order", "id").first()
if first:
url = first.image.url
if not url:
return ""
return format_html(
'<img src="{}" style="max-height:48px;border-radius:4px;" />',
url,
)
@admin.display(description="配图预览")
def image_preview(self, obj: Memory) -> str:
chunks: list[str] = []
if obj.image:
chunks.append(
format_html(
'<div class="mb-2"><span style="font-size:11px;color:#666">主图</span><br>'
'<img src="{}" style="max-width:280px;border-radius:8px;" /></div>',
obj.image.url,
)
)
for p in obj.photos.order_by("sort_order", "id"):
chunks.append(
format_html(
'<img src="{}" style="max-width:200px;border-radius:6px;margin:4px;" />',
p.image.url,
)
)
if not chunks:
return ""
return mark_safe("".join(str(c) for c in chunks))
@admin.register(Guestbook)
class GuestbookAdmin(JournalStaffAccessMixin, admin.ModelAdmin):
list_display = ("nickname", "short_message", "created_at")
search_fields = ("nickname", "message")
readonly_fields = ("created_at",)
@admin.display(description="留言")
def short_message(self, obj: Guestbook) -> str:
return obj.message[:80] + ("" if len(obj.message) > 80 else "")
@admin.register(Config)
class ConfigAdmin(admin.ModelAdmin):
"""
站点配置单独写权限:不继承 JournalStaffAccessMixin避免 MRO/多重继承下
has_change_permission 未按预期生效,导致 change 页全部为只读且 submit_row 不显示「保存」。
"""
save_on_top = True
list_display = (
"site_title",
"together_since",
"unlock_at",
)
list_display_links = ("site_title",)
fieldsets = (
(
"站点",
{"fields": ("site_title",)},
),
(
"时间",
{
"fields": (
"together_since",
"unlock_at",
),
"description": "「在一起」时间用于首页计数。unlock_at 已不使用,可留空。",
},
),
)
def _staff_ok(self, request) -> bool:
u = request.user
return bool(
getattr(u, "is_active", False)
and getattr(u, "is_authenticated", False)
and (getattr(u, "is_staff", False) or getattr(u, "is_superuser", False))
)
def has_module_permission(self, request):
return self._staff_ok(request)
def has_view_permission(self, request, obj=None):
return self._staff_ok(request)
def has_change_permission(self, request, obj=None):
return self._staff_ok(request)
def has_add_permission(self, request):
if not self._staff_ok(request):
return False
return not Config.objects.exists()
def has_delete_permission(self, request, obj=None):
return False