自定义管理表单¶
通过注册Question模型admin.site.register(Question),Django能够构造默认的表单表示。通常,您需要自定义管理表单的外观和工作方式。你可以通过在注册对象时告诉Django你想要的选项来做到这一点。
让我们通过重新排序编辑表单上的字段来了解它是如何工作的。将admin.site.register(Question)线替换为:
民调/ 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)
您将遵循此模式 - 创建模型管理类,然后将其作为第二个参数传递给admin.site.register()- 任何时候您需要更改模型的管理选项。
上述特定更改使“发布日期”出现在“问题”字段之前:
字段已重新排序
仅使用两个字段并不令人印象深刻,但对于具有数十个字段的管理表单,选择直观的顺序是一个重要的可用性细节。
说到有几十个字段的表单,您可能希望将表单拆分为字段集:
民调/ 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的标题。这就是我们现在的形式:
表单现在有字段集
添加相关对象¶
好的,我们有问题管理页面,但是Question有多个 Choices,管理页面不显示选项。
然而。
有两种方法可以解决这个问题。第一个是Choice 像我们一样向管理员注册Question。这很简单:
民调/ admin.py中¶
from django.contrib import admin
from .models import Choice, Question
…
admin.site.register(Choice)
现在,“选择”是Django管理员中的一个可用选项。“添加选项”表单如下所示:
选择管理页面
在该表单中,“问题”字段是包含数据库中每个问题的选择框。Django知道ForeignKey应该在管理员中将a表示为一个框。在我们的例子中,此时只存在一个问题。
另请注意“问题”旁边的“添加另一个”链接。与ForeignKey另一个有关系的每个对象 都可以免费获得。当您单击“添加另一个”时,您将看到一个带有“添加问题”表单的弹出窗口。如果您在该窗口中添加一个问题并单击“保存”,Django会将问题保存到数据库,并在您正在查看的“添加选项”表单中将其作为所选选项动态添加。
但是,实际上,这是Choice向系统添加对象的低效方法。如果你可以在创建Question对象时直接添加一堆Choices,那会更好 。让我们实现这一目标。
删除模型的register()调用Choice。然后,编辑Question 注册码阅读:
民调/ 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- 并且每次返回已更改对象的“更改”页面时,您将获得另外三个额外插槽。
在三个当前位置的末尾,您将找到“添加另一个选择”链接。如果单击它,将添加一个新插槽。如果要删除添加的插槽,可以单击添加插槽右上角的X. 请注意,您无法删除原来的三个插槽。此图显示了添加的插槽:
动态添加附加插槽
但是有一个小问题。显示用于输入相关Choice对象的所有字段需要大量屏幕空间。出于这个原因,Django提供了一种显示内联相关对象的表格方式; 你只需要将ChoiceInline声明改为:
民调/ admin.py中¶
class ChoiceInline(admin.TabularInline):
#…
使用它TabularInline(而不是StackedInline),相关对象以更紧凑,基于表格的格式显示:
现在添加问题页面有更紧凑的选择
请注意,还有一个额外的“删除?”列,允许删除使用“添加另一个选择”按钮添加的行和已保存的行。
自定义管理员更改列表¶
现在问题管理页面看起来很好,让我们对“更改列表”页面进行一些调整 - 显示系统中所有问题的页面。
这就是它在这一点上的样子:
民意调查更改列表页面
默认情况下,Django显示str()每个对象。但有时如果我们可以显示单个字段会更有帮助。为此,请使用 list_displayadmin选项,该选项是要在对象的更改列表页面上显示的字段名称元组:
民调/ admin.py中¶
class QuestionAdmin(admin.ModelAdmin):
# …
list_display = (‘question_text’, ‘pub_date’)
为了更好的衡量,我们还要包含教程2中的was_published_recently() 方法:
民调/ admin.py中¶
class QuestionAdmin(admin.ModelAdmin):
# …
list_display = (‘question_text’, ‘pub_date’, ‘was_published_recently’)
现在,问题更改列表页面如下所示:
民意调查更改列表页面,已更新
您可以单击列标题以按这些值排序 - 除了was_published_recently标题之外,因为不支持按任意方法的输出进行排序。另请注意,was_published_recently默认情况下,列标题 是方法的名称(下划线替换为空格),并且每行包含输出的字符串表示形式。
您可以通过为该方法(in polls/models.py)提供一些属性来改进它,如下所示:
民调/ models.py中¶
class Question(models.Model):
# …
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
was_published_recently.admin_order_field = ‘pub_date’
was_published_recently.boolean = True
was_published_recently.short_description = ‘Published recently?’
有关这些方法属性的更多信息,请参阅 list_display。
polls/admin.py再次编辑您的文件,并在Question更改列表页面中添加一项改进 :使用 list_filter。将以下行添加到 QuestionAdmin:
list_filter = [‘pub_date’]
这会添加一个“过滤器”侧边栏,让人们按pub_date字段过滤更改列表 :
民意调查更改列表页面,已更新
显示的过滤器类型取决于您要过滤的字段类型。因为pub_date是DateTimeField,Django知道给出适当的过滤选项:“任何日期”,“今天”,“过去7天”,“本月”,“今年”。
这很好。让我们添加一些搜索功能:
search_fields = [‘question_text’]
这会在更改列表的顶部添加一个搜索框。当某人输入搜索词时,Django将搜索该question_text字段。您可以使用任意数量的字段 - 尽管因为它LIKE在后台使用查询,将搜索字段的数量限制为合理的数字将使您的数据库更容易进行搜索。
现在也是注意更改列表为您提供免费分页的好时机。默认设置是每页显示100个项目。,,,,和 所有的工作在一起,就像你认为他们应该。Change list paginationsearch boxesfiltersdate-hierarchiescolumn-header-ordering
自定义管理员外观¶
显然,在每个管理页面的顶部都有“Django管理”是荒谬的。它只是占位符文本。
但是,使用Django的模板系统很容易改变。Django管理员由Django本身提供支持,其界面使用Django自己的模板系统。
自定义项目的模板¶
templates在项目目录(包含的目录)中创建一个目录manage.py。模板可以存放在Django可以访问的文件系统的任何位置。(Django以您的服务器运行的任何用户身份运行。)但是,将模板保留在项目中是一个很好的约定。
打开您的设置文件(mysite/settings.py请记住)并DIRS在TEMPLATES设置中添加一个 选项:
mysite /settings.py¶
TEMPLATES = [
{
‘BACKEND’: ‘django.template.backends.django.DjangoTemplates’,
‘DIRS’: [os.path.join(BASE_DIR, ‘templates’)],
‘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模板时要检查的文件系统目录列表; 这是一条搜索路径。
组织模板
就像静态文件一样,我们可以将所有模板放在一个大模板目录中,并且它可以很好地工作。但是,属于特定应用程序的模板应放在该应用程序的模板目录(例如polls/templates)中,而不是项目的(templates)。我们将在可重用的应用程序教程 中更详细地讨论 为什么我们这样做。
现在创建一个名为admininside 的目录templates,并将模板admin/base_site.html从Django本身(django/contrib/admin/templates)的源代码中的默认Django管理模板目录中复制到该目录中。
Django源文件在哪里?
如果您在查找Django源文件在系统中的位置时遇到困难,请运行以下命令:
/
$ python -c “import django; print(django.path)”
然后,只需编辑文件,并根据自己的网站名称替换 (包括花括号)。你应该得到一段代码,如:{{ site_header|default:_(‘Django administration’) }}
{% block branding %}
Polls Administration
{% endblock %} 我们使用这种方法来教你如何覆盖模板。在实际项目中,您可能会使用该django.contrib.admin.AdminSite.site_header属性来更轻松地进行此特定自定义。此模板文件包含许多类似 和的文本。在和标签是Django的模板语言的一部分。当Django呈现时,将评估此模板语言以生成最终的HTML页面,就像我们在教程3中看到的那样。{% block branding %}{{ title }}{%{{admin/base_site.html
请注意,任何Django的默认管理模板都可以被覆盖。要覆盖模板,只需执行与之相同的操作base_site.html- 将其从默认目录复制到自定义目录中,然后进行更改。
自定义应用程序的模板¶
精明的读者会问:但如果DIRS默认为空,Django如何找到默认的管理模板?答案是,自APP_DIRS设置为True,Django会自动templates/在每个应用程序包中查找子目录,以用作后备(不要忘记这 django.contrib.admin是一个应用程序)。
我们的民意调查应用程序不是很复杂,也不需要自定义管理模板。但是如果它变得越来越复杂并且需要修改Django的标准管理模板以实现其某些功能,那么修改应用程序的模板(而不是项目中的模板) 会更加明智。这样,您可以将民意调查应用程序包含在任何新项目中,并确保它可以找到所需的自定义模板。
有关Django如何找到其模板的更多信息,请参阅模板加载文档。
自定义管理索引页面¶
在类似的说明中,您可能希望自定义Django管理员索引页面的外观。
默认情况下,它INSTALLED_APPS按字母顺序显示已在管理应用程序中注册的所有应用程序。您可能希望对布局进行重大更改。毕竟,索引可能是管理员最重要的页面,它应该易于使用。
要自定义的模板是admin/index.html。(与admin/base_site.html上一节中的相同 - 将其从默认目录复制到自定义模板目录)。编辑文件,你会看到它使用一个名为的模板变量app_list。该变量包含每个已安装的Django应用程序。您可以以您认为最好的方式将链接硬编码到特定于对象的管理页面,而不是使用它。