编写您的第一个Django应用程序,第7部分

本教程从以下位置开始 Tutorial 6 停下来了。我们将继续使用Web投票应用程序,并将重点放在定制Django的自动生成的管理站点上,该站点最初是在 Tutorial 2

从哪里获得帮助:

如果您在阅读本教程时遇到困难,请访问 Getting Help 部分的常见问题解答。

自定义管理表单

通过注册 Question 模型 admin.site.register(Question) ,Django能够构建默认的表单表示。通常,您会想要自定义管理表单的外观和工作方式。您可以在注册对象时告诉Django您想要的选项来实现这一目标。

让我们看看如何通过重新排序编辑表单上的字段。更换 admin.site.register(Question) 行:

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)

您将遵循此模式--创建一个模型管理类,然后将其作为第二个参数传递给 admin.site.register() --任何时候您需要更改模型的管理选项。

上述特殊更改使“发布日期”位于“问题”字段之前:

字段已重新排序

只有两个字段并不令人印象深刻,但对于具有数十个字段的管理表单,选择直观的顺序是一个重要的可用性细节。

说到具有数十个字段的表单,您可能想将表单拆分为字段集:

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 是字段集的标题。以下是我们的表格现在的样子:

表单现在有字段集

自定义管理更改列表

既然“问题”管理页面看起来不错,让我们对“更改列表”页面(显示系统中所有问题的页面)进行一些调整。

以下是目前情况:

民意调查更改列表页面

默认情况下,Django显示 str() 每个对象的。但有时,如果我们可以显示单个字段,那会更有帮助。为此,请使用 list_display 管理选项,这是要在对象的更改列表页面上显示为列的字段名称列表:

polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ["question_text", "pub_date"]

为了更好地衡量,我们还包括 was_published_recently() 方法来自 Tutorial 2

polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ["question_text", "pub_date", "was_published_recently"]

现在问题更改列表页面如下:

民意调查更改列表页面,已更新

您可以单击列标题按这些值排序--除非是 was_published_recently 标头,因为不支持按任意方法的输出排序。另请注意,的列标题 was_published_recently 默认情况下,是方法的名称(用空白替换了虚线),并且每一行都包含输出的字符串表示形式。

您可以通过使用 display() 该方法上的装饰器(扩展 polls/models.py 在中创建的文件 Tutorial 2 ),如下:

polls/models.py
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

有关通过装饰器配置的属性的更多信息,请参阅 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-hierarchies ,以及 column-header-ordering 所有人都像您认为应该的那样一起工作。

自定义管理外观和感觉

显然,在每个管理页面的顶部设置“Django管理”是荒谬的。这只是占位符文本。

不过,您可以使用Django的模板系统来更改它。Django管理员由Django本身提供支持,其界面使用Django自己的模板系统。

定制你 project's 模板

创建一个 templates 目录在您的 djangotutorial 目录.模板可以位于Django可以访问的文件系统上的任何地方。(Django作为您的服务器运行的任何用户运行。)然而,将模板保留在项目中是一个很好的遵循惯例。

打开您的设置文件 (mysite/settings.py ,记住)并添加一个 DIRS 选项中的 TEMPLATES 设置:

mysite/settings.py
TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [BASE_DIR / "templates"],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

DIRS 是加载Django模板时要检查的文件系统目录列表;这是一个搜索路径。

组织模板

Just like the static files, we could have all our templates together, in one big templates directory, and it would work perfectly well. However, templates that belong to a particular application should be placed in that application's template directory (e.g. polls/templates) rather than the project's (templates). We'll discuss in more detail in the reusable apps tutorial why we do this.

现在创建一个名为 admin 里边 templates ,并复制模板 admin/base_site.html 在Django本身的源代码中的默认Django管理模板目录中 (django/contrib/admin/templates )添加到该目录中。

Django源文件在哪里?

如果您在系统上找到Django源文件的位置时遇到困难,请运行以下命令:

$ python -c "import django; print(django.__path__)"
...\> py -c "import django; print(django.__path__)"

然后,编辑文件并替换 {{ site_header|default:_('Django administration') }} (包括花括号),以您认为合适的方式使用您自己的网站名称。您最终应该得到一段代码,如下所示:

{% block branding %}
<div id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></div>
{% if user.is_anonymous %}
  {% include "admin/color_theme_toggle.html" %}
{% endif %}
{% endblock %}

我们使用这种方法来教您如何覆盖模板。在实际项目中,您可能会使用 django.contrib.admin.AdminSite.site_header 属性以更轻松地进行此特定的定制。

此模板文件包含大量文本,例如 {% block branding %}{{ title }} 。这个 {%{{ 标签是Django模板语言的一部分。当姜戈渲染 admin/base_site.html ,将评估此模板语言以生成最终的HTML页面,就像我们在 Tutorial 3

请注意,Django的任何默认管理模板都可以被覆盖。要覆盖模板,请执行与所做的相同的操作 base_site.html --将其从默认目录复制到您的自定义目录中,并进行更改。

定制你 application's 模板

精明的读者会问:但如果 DIRS 默认为空,Django如何找到默认的管理模板?答案是,由于 APP_DIRS 设置为 True ,Django自动寻找 templates/ 在每个应用程序包中设置,用作后备(不要忘记 django.contrib.admin 是应用程序)。

我们的民意调查应用程序并不很复杂,并且不需要自定义管理模板。但如果它变得越来越复杂,并且需要修改Django的一些功能的标准管理模板,那么修改 application's 模板,而不是 project .这样,您就可以将民意调查应用程序包含在任何新项目中,并确保它会找到所需的自定义模板。

请参阅 template loading documentation 了解有关Django如何查找其模板的更多信息。

自定义管理索引页面

类似地,您可能想要自定义Django管理索引页面的外观和感觉。

默认情况下,它显示中的所有应用程序 INSTALLED_APPS 已在管理应用程序中注册,按字母顺序。您可能想要对布局进行重大更改。毕竟,索引可能是管理员最重要的页面,而且应该很容易使用。

要自定义的模板是 admin/index.html . (Do与 admin/base_site.html 在上一节中--将其从默认目录复制到您的自定义模板目录)。编辑该文件,您会看到它使用一个名为 app_list .该变量包含每个已安装的Django应用程序。您可以以您认为最好的任何方式硬编码指向特定对象管理页面的链接,而不是使用该变量。

当您对管理员感到满意时,请阅读 part 8 of this tutorial 学习如何使用第三方程序包。