7. 自定义后台
自定义表单
通过admin.site.register(Question)
注册Question
模型,Django会创建默认的表单在后台显示。但有时需要自定义后台的显示,可以通过继承admin.ModelAdmin
实现:
# polls/admin.py
from django.contrib import admin
from .models import Question
class QuestionAdmin(admin.ModelAdmin):
fields = ["pub_date", "question_text"]
admin.site.register(Question, QuestionAdmin)
fields
定义了显示的内容。
如果表单字段很多,你可能想将它们分成不同部分:
from django.contrib import admin
from .models import Question
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None, {"fields": ["question_text"]}),
("Date information", {"fields": ["pub_date"]}),
]
admin.site.register(Question, QuestionAdmin)
添加关联的对象
一个问题有多个选项,但后台却没有显示选项。有两个方法可以解决这个问题。一是像注册Question一样,注册Choice。
from django.contrib import admin
from .models import Choice, Question
# ...
admin.site.register(Choice)
现在可以看到选项,但是现在只能逐个创建选项并关联问题。
我们想要在创建问题时直接添加很多个选项:将polls/admin.py修改为如下内容:
from django.contrib import admin
from .models import Choice, Question
class ChoiceInline(admin.StackedInline):
model = Choice
extra = 3
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None, {"fields": ["question_text"]}),
("Date information", {"fields": ["pub_date"], "classes": ["collapse"]}),
]
inlines = [ChoiceInline]
admin.site.register(Question, QuestionAdmin)
这告诉 Django:Choice 对象要在 Question 后台页面编辑。默认提供3个选项(extra=3
)。
不过,现在选项占用的区域太大了。Django 提供了一种表格式的单行显示关联对象的方法。要使用它,只需按如下形式修改 ChoiceInline 声明:
class ChoiceInline(admin.TabularInline):
...
通过 TabularInline (替代 StackedInline ),关联对象以一种表格式的方式展示,显得更加紧凑。
自定义后台更改列表
现在投票的后台页看起来很不错,让我们对问题列表页面进行一些调整——改成一个能展示系统中所有投票的页面。默认情况下,Django 显示每个对象的 str() 返回的值。但有时如果我们能够显示单个字段,它会更有帮助。为此,使用 list_display
属性,它是一个包含要显示的字段名的元组,在更改列表页中以列的形式展示这个对象:
class QuestionAdmin(admin.ModelAdmin):
# ...
list_display = ["question_text", "pub_date"]
另外,让我们把 教程第 2 部分 中的 was_published_recently() 方法也加上:
class QuestionAdmin(admin.ModelAdmin):
# ...
list_display = ["question_text", "pub_date", "was_published_recently"]
你可以通过在该方法上(在 polls/models.py 中)使用 display() 装饰器来改进:
from django.db import models
from django.contrib import admin
from django.utils import timezone
import datetime
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField("date published")
def __str__(self):
return self.question_text
@admin.display(
boolean=True,
ordering="pub_date",
description="Published recently?",
)
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
接下来我们添加一个过滤器。编辑文件 polls/admin.py,将以下代码添加至 QuestionAdmin: list_filter = ["pub_date"]
这样做添加了一个“过滤器”侧边栏,允许人们以 pub_date 字段来过滤列表:
让我们再添加搜索功能: search_fields = ["question_text"]
在列表的顶部有了一个搜索框。当输入待搜项时,Django 将搜索 question_text 字段。(你可以使用任意多的字段)
说明
完整的教程可以前往官网:https://docs.djangoproject.com/zh-hans/4.2/intro/ 本教程省略了一些内容,如第5部分的测试,第8部分的扩展。
相关的代码:https://github.com/liufei65536/django_project