Files
school-meal/backend/meals/admin.py
T
Chunyu 5fcec79298 fix: 修复 admin 后台分页等样式丢失问题
- admin/base.html 加载 Django admin CSS (base/changelists/forms/responsive)

- registration/base.html 加载 Django admin CSS (base/forms/login)

- jazzmin/css/main.css 添加 Django admin CSS 变量映射到 Bootstrap 5

- 新增分页/表格/按钮/搜索/过滤器等 Bootstrap 兼容样式

- admin.py list_per_page 50->20
2026-08-29 14:02:02 +08:00

88 lines
3.5 KiB
Python

from django.contrib import admin
from django.utils.html import format_html, mark_safe
from .models import Cuisine, Dish
@admin.action(description='启用所选菜系')
def activate_cuisines(modeladmin, request, queryset):
queryset.update(is_active=True)
@admin.action(description='停用所选菜系')
def deactivate_cuisines(modeladmin, request, queryset):
queryset.update(is_active=False)
@admin.register(Cuisine)
class CuisineAdmin(admin.ModelAdmin):
list_display = ('name', 'description', 'sort_order', 'is_active', 'dish_count_display', 'created_at')
list_editable = ('sort_order', 'is_active')
list_filter = ('is_active',)
search_fields = ('name',)
list_per_page = 20
actions = [activate_cuisines, deactivate_cuisines]
@admin.display(description='菜品数')
def dish_count_display(self, obj):
count = obj.dishes.count()
return format_html('<span style="font-weight:600">{}</span>', count)
@admin.action(description='启用所选菜品(参与自动生成)')
def activate_dishes(modeladmin, request, queryset):
queryset.update(is_active=True)
@admin.action(description='停用所选菜品(不再参与自动生成)')
def deactivate_dishes(modeladmin, request, queryset):
queryset.update(is_active=False)
@admin.register(Dish)
class DishAdmin(admin.ModelAdmin):
list_display = ('name', 'cuisine_display', 'dish_type_display', 'ingredient_detail', 'protein', 'fat', 'calorie', 'nutri_badge', 'is_active', 'created_at')
list_filter = ('dish_type', 'cuisine', 'is_active')
search_fields = ('name', 'ingredient_detail', 'cuisine__name', 'pinyin')
list_editable = ('ingredient_detail', 'protein', 'fat', 'calorie', 'is_active')
list_per_page = 20
actions = [activate_dishes, deactivate_dishes]
fieldsets = (
(None, {'fields': ('name', 'dish_type', 'cuisine', 'is_active')}),
('营养信息', {'fields': ('ingredient_detail', 'protein', 'fat', 'calorie')}),
('其他', {'fields': ('description',), 'classes': ('collapse',)}),
)
@admin.display(description='菜系', ordering='cuisine')
def cuisine_display(self, obj):
if obj.cuisine:
return obj.cuisine.name
return '—'
@admin.display(description='营养提示', ordering='calorie')
def nutri_badge(self, obj):
badges = []
if obj.dish_type == 'meat' and obj.fat >= 20:
badges.append('<span class="badge badge-danger">高脂</span>')
if obj.dish_type == 'meat' and obj.calorie >= 300:
badges.append('<span class="badge badge-warning">高热量</span>')
if obj.dish_type in ('meat', 'veg') and obj.protein >= 15:
badges.append('<span class="badge badge-success">高蛋白</span>')
if obj.dish_type == 'veg' and obj.fat <= 3 and obj.calorie <= 60:
badges.append('<span class="badge badge-info">清淡</span>')
return mark_safe('&nbsp;'.join(badges)) if badges else '—'
@admin.display(description='类型')
def dish_type_display(self, obj):
colors = {'meat': '#d9534f', 'veg': '#5cb85c', 'soup': '#5bc0de', 'staple': '#f0ad4e'}
return format_html(
'<span style="color:{};font-weight:600">{}</span>',
colors.get(obj.dish_type, '#999'),
dict(Dish.TYPE_CHOICES).get(obj.dish_type, obj.dish_type),
)
admin.site.site_header = '学校订餐菜单管理系统'
admin.site.site_title = '学校订餐菜单管理'
admin.site.index_title = '菜单管理后台'