编写第一个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 ),详情如下:

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-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": [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 )我们将在 reusable apps tutorial why 我们这样做。

现在创建一个名为 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>
{% endblock %}

我们使用这种方法来教您如何重写模板。在实际的项目中,您可能会使用 django.contrib.admin.AdminSite.site_header 属性可以更容易地进行此特定的自定义。

此模板文件包含大量类似 {{% block branding %}}{{{{ title }}}} . 这个 {{%{{{{ 标记是Django模板语言的一部分。当Django渲染时 admin/base_site.html ,此模板语言将被评估为生成最终的HTML页,就像我们在中看到的那样 Tutorial 3 .

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

自定义您的 应用程序的 模板

精明的读者会问:但如果 DIRS 默认情况下为空,Django如何查找默认管理模板?答案是,因为 APP_DIRS 设置为 True ,Django自动查找 templates/ 每个应用程序包中的子目录,用作回退(不要忘记 django.contrib.admin 是一个应用程序)。

我们的投票应用程序不是很复杂,不需要自定义管理模板。但是,如果它变得更复杂,需要修改django的标准管理模板以实现某些功能,那么修改 应用程序的 模板,而不是 项目 . 这样,您就可以在任何新项目中包含投票应用程序,并确保它可以找到所需的自定义模板。

template loading documentation 有关Django如何查找模板的详细信息。

自定义管理索引页

在类似的注释中,您可能希望自定义django管理索引页的外观。

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

要自定义的模板是 admin/index.html . (做同样的事 admin/base_site.html 在上一节中——将其从默认目录复制到自定义模板目录)。编辑该文件,您将看到它使用一个名为 app_list . 该变量包含所有已安装的django应用程序。不用它,你可以用你认为最好的方式硬编码链接到特定对象的管理页面。

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