编写你的第一个 Django 应用程序,第 7 部分 — Django 文档

来自菜鸟教程
Django/docs/3.0.x/intro/tutorial07
跳转至:导航、​搜索

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

本教程从 教程 6 停止的地方开始。 我们将继续使用 Web-poll 应用程序,并将专注于自定义 Django 自动生成的管理站点,我们在 教程 2 中首次探讨了该站点。

从哪里获得帮助:

如果您在阅读本教程时遇到问题,请转到常见问题解答的 获取帮助 部分。


自定义管理表单

通过将 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() - 任何时候您需要更改模型的管理选项。

上面的这个特殊更改使“发布日期”出现在“问题”字段之前:

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

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

民意调查/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 中每个元组的第一个元素是字段集的标题。 这是我们的表单现在的样子:

Form has fieldsets now

自定义管理员更改列表

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

这是此时的样子:

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

民意调查/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')

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

Polls change list page, updated 您可以单击列标题以按这些值排序——was_published_recently 标题除外,因为不支持按任意方法的输出排序。 另请注意,was_published_recently 的列标题默认是方法的名称(下划线替换为空格),并且每一行都包含输出的字符串表示形式。

您可以通过为该方法(在 polls/models.py 中)提供一些属性来改进它,如下所示:

民意调查/模型.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 字段过滤更改列表:

Polls change list page, updated 显示的过滤器类型取决于您过滤的字段类型。 因为 pub_dateDateTimeField,所以 Django 知道提供适当的过滤选项:“任何日期”、“今天”、“过去 7 天”、“本月”、“今年”。

这塑造得很好。 让我们添加一些搜索功能:

search_fields = ['question_text']

这会在更改列表的顶部添加一个搜索框。 当有人输入搜索词时,Django 将搜索 question_text 字段。 您可以使用任意数量的字段——尽管因为它在后台使用 LIKE 查询,将搜索字段的数量限制为合理的数量将使您的数据库更容易进行搜索。

现在也是注意更改列表为您提供免费分页的好时机。 默认是每页显示 100 个项目。 更改列表分页搜索框过滤器日期层次结构列标题排序所有像您认为的那样一起工作。


自定义管理外观

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

不过,您可以使用 Django 的模板系统更改它。 Django admin 由 Django 本身提供支持,其接口使用 Django 自己的模板系统。

自定义您的 项目的 模板

在您的项目目录(包含 manage.py 的目录)中创建一个 templates 目录。 模板可以位于文件系统上 Django 可以访问的任何位置。 (Django 以您的服务器运行的任何用户身份运行。)但是,将模板保留在项目中是一个很好的约定。

打开您的设置文件(mysite/settings.py ,记住)并添加一个 :setting:`目录 ` 选项中 :设置:`模板` 环境:

我的网站/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',
            ],
        },
    },
]

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

整理模板

就像静态文件一样,我们 可以 将所有模板放在一起,放在一个大模板目录中,它会运行得非常好。 但是,属于特定应用程序的模板应放置在该应用程序的模板目录中(例如 polls/templates) 而不是项目的 (templates)。 我们将在 可重用应用教程 为什么 中更详细地讨论我们这样做。


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

Django 源文件在哪里?

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


然后,编辑文件并将 模板:Site header(包括花括号)替换为您认为合适的站点名称。 你应该得到一段代码,如:

{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1>
{% endblock %}

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

该模板文件包含大量文本,如 {% block branding %}模板:Title{%{{ 标签是 Django 模板语言的一部分。 当 Django 呈现 admin/base_site.html 时,将评估此模板语言以生成最终的 HTML 页面,就像我们在 教程 3 中看到的那样。

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


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

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

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

有关 Django 如何找到其模板的更多信息,请参阅 模板加载文档


自定义管理索引页面

同样,您可能希望自定义 Django 管理索引页面的外观。

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

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


下一步是什么?

初学者教程到此结束。 同时,您可能想查看有关 从这里开始 的一些指示。

如果您熟悉 Python 打包并且有兴趣学习如何将投票变成“可重用的应用程序”,请查看 高级教程:如何编写可重用的应用程序