初学教程最后一部分:
https://docs.djangoproject.com/zh-hans/3.2/intro/tutorial07/
自定义后台表单
当前表单显示:Question text + Data published
重排字段:创建一个模型后台类,将其作为第二个参数传递给
admin.site.register
# 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)
字段顺序变化:Data published + Question text
当字段个数过多时,考虑将表单分为几个字段集:
# polls/admin.py
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)
fieldsets
是一个由两个元组组成的列表,其中每个元组代表管理表单页面上的一个 <fieldset>
。
这两个元组的格式是 (name, field_options)
,其中 name
是代表字段集标题的字符串,field_options
是关于字段集的信息字典,包括要在其中显示的字段列表。
显示效果如下,已经分为两个部分:
添加关联的对象
当前投票后台不显示Choice选项,有两种方法解决。
后台注册Choice
(该方法比较低效)
# polls/admin.py
from django.contrib import admin
from .models import Choice, Question
# ...
admin.site.register(Choice)
添加选项表单效果:
其中,Question字段是一个包含数据库中所有投票的选择框。在Choice模型中将Question设置为外键,而外键在Django后台会以选择框的形式展示:
Question右侧的添加按钮可以添加新的投票问题。
在创建“投票”对象时直接添加多个选项
让Choice对象在Question后台页面编辑,默认提供3个额外的(不包括已存在的选项)选项字段。
# polls/admin.py 移除Choice注册代码
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)
重新加载"添加投票"页面:
页面显示有三个由extra定义的选项插槽,每次返回到已创建的对象的修改页面时,都会显示三个新的插槽。
下方点击可添加新选项,选项右方点击X删除选项。
当前问题:显示所有关联的Choice对象字段占据了过多的屏幕区域。
考虑表格式单行显示关联对象的方法,将ChoiceInline
的父类admin.StackedInline
用admin.TabularInline
替代 :
class ChoiceInline(admin.TabularInline):
显示选项更紧凑:
自定义后台更改列表
当前后台列表:
展示所有投票信息
调整目标:能展示系统中所有投票信息(包括pub_date
,was_published_recently()
)的页面。
list_display
:用于控制哪些字段显示在管理的变更列表页面,包含要显示字段名的元组,在更改列表中以列的形式展示这个对象。
# polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
# ...
list_display = ('question_text', 'pub_date', 'was_published_recently')
调整效果如下:
可以点击列标题进行排序:
设置display属性
对于was_published_recently
列标题默认使用方法名,可以通过装饰器display()
设置名称等属性以改进:
from django.contrib import admin
class Question(models.Model):
# ...
@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
其中boolean
决定结果是否显示为图标;ordering
表示排序依据,在字段名前使用连字符前缀如-pub_date
表示降序;description
用于自定义列的标题。
显示效果:
添加过滤器
使用 list_filter
添加一个过滤器,可以根据pub_date字段过滤列表
# polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
# ...
list_filter = ['pub_date']
过滤效果(过去7天):
添加搜索框
(按照question_text
匹配搜索项)
# polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
# ...
search_fields = ['question_text']
搜索效果:
自定义后台界面和风格
当前后台页面顶部显示Django administration
,可以通过模板系统修改。
自定义工程模板
在工程目录下创建templates
子目录用于存放模板。
在设置文件中,给TEMPLATES
设置添加DIRS
选项:
# mysite/settings.py
TEMPLATES = [
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'], # 添加DIRS选项
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
DIRS
是一个包含多个系统目录的文件列表,用于在载入 Django 模板时使用,是一个待搜索路径。
在templates
目录内创建admin
子目录,将存放 Django 默认模板的目录(django/contrib/admin/templates
)内的模板文件 admin/base_site.html
复制到这个admin
目录内。
Django源文件目录(使用anaconda虚拟环境的目录):
D:\anaconda3\envs\django_env\Lib\site-packages\django\contrib\admin\templates
可以通过以下命令行命令找到源目录:
python -c "import django; print(django.__path__)"
修改前base_site.html
:
{% extends "admin/base.html" %}
{% block title %}{% if subtitle %}{{ subtitle }} | {% endif %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}
{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">{{ site_header|default:_('Django administration') }}</a></h1>
{% endblock %}
{% block nav-global %}{% endblock %}
将默认网页头部信息修改为应用名polls Administration
:
{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1>
{% endblock %}
修改效果:
实际工程中,对于site_header
更多使用 django.contrib.admin.AdminSite.site_header
进行简单的定制。
自定义应用模板
DIRS
默认为空,但APP_DIRS
设置为True
,Django会自动在每个应用包内递归查找 templates/
子目录( django.contrib.admin
也是一个应用)。
当前应用较简单,不需要自定义后台模板。
对于复杂应用,相比修改工程模板,更建议修改应用模板。
查找过程可参考加载模板文档。
自定义后台主页
目标:自定义后台索引页的外观
索引页默认按字母排序显示所有配置在 INSTALLED_APPS
中,已通过后台应用注册的应用。
复写模板:admin/index.html
此文件使用了一个叫做 app_list
的模板变量。这个变量包含了每个安装的 Django 应用。你可以用任何你期望的硬编码链接(链接至特定对象的管理页)替代使用这个变量。