Django框架(八)编写第一个Django应用程序——第七部分

目录

编写第一个Django应用程序,第七部分

自定义管理表单

添加相关对象

自定义管理列表

自定义管理外观

自定义项目的模板


编写第一个Django应用程序,第七部分

我们将继续web-poll应用程序,并将专注于自定义Django自动生成的管理站点。

自定义管理表单

通过在admin.site.register(Question)中注册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"]}),
        ("日期 information", {"fields": ["pub_date"]})
    ]

admin.site.register(Question, QuestionAdmin)

fieldsets中每个元组的第一个元素是字段集区域的标题。下面是我们表单现在的样子:

添加相关对象

好了,我们现在有了问题的管理页面,但是一个问题是有多个选项,我们现在还没有选项的管理页面。

有两种方式可以解决这个问题。第一个就是在admin中注册Choice,就像在admin中注册Question一样:

# polls/admin.py
from django.contrib import admin

from .models import Choice, Question

# ...
admin.site.register(Choice)

现在“Choices”在Django管理中是一个可用的选项。“Add Choice”表单看起来像这样:

在该表单中,“Question”字段是一个选择框,包含数据库中的每个问题。Django知道ForeignKey应该在admin中被表示为<select>框。在我们当前的程序中,数据库中只有一个问题。

还要注意“question”旁边的“Add another question”链接。每个具有ForeignKey关系的对象都可以自动获得此属性。当你点击“Add another question”时,你会看到一个弹出窗口,里面有“添加问题”表单。如果你在这个窗口中添加了一个问题,然后点击“保存”,Django会将这个问题保存到数据库中,并动态地将它添加到你正在查看的“添加选项”表单中。

但实际上,这是一种低效的添加Choice的方式。一般的做法是,在添加Question的时候,同时为该问题添加选项。让我们来实现这种方式。

删除Choice模型的register()调用,然后,修改Question的注册代码如下:

# polls/admin.py
from django.contrib import admin

from .models import Question, Choice

class ChoiceInline(admin.StackedInline):
    model = Choice
    extra = 3

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None, {"fields": ["question_text"]}),
        ("日期 information", {"fields": ["pub_date"]})
    ]
    inlines = [ChoiceInline]

admin.site.register(Question, QuestionAdmin)

这告诉Django,“Choice”对象是在Question管理页面中进行编辑的,默认设置为3个选项。打开“Add question”页面,你会看到以下页面:

它的工作原理是这样的:有三个插槽用于相关的选择(由extra指定),每次你回到“更改”页面查看已经创建的对象时,你将获得另外三个插槽。

在当前三个插槽的末尾,你会发现一个“添加另一个选择”链接。如果你点击它,一个新的插槽将被添加。如果要移除已添加的槽位,可以单击槽位右上方的“X”。这张图片显示了一个增加的插槽:

不过有一个小问题。要显示用于输入Choice对象的相所有字段,需要占用大量屏幕空间。因此,Django提供了一种表格方式来显示相关内联对象。要使用它,将ChoiceInline声明更改为:

class ChoiceInline(admin.TabularInline): ...

使用TabularInline(而不是StackedInline),相关对象将以更紧凑的基于表格的形式显示:

自定义管理列表

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

现在看起来是这样的:

默认情况下,Django使用str()方法显示每个对象。但有时候,能够单独显示对象中的字段,将会很有帮助。要做到这一点,使用list_display管理选项,这是一个字段名称的元组,以列的形式显示在对象的更改列表页面上:

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

为了展示内容更好,让我们把was_published_recently()也添加进去:

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

现在问题列表页面看起来应该像下面这样:

你可以点击列标题来进行排序,除了was_published_recently标题,因为不支持对方法的输出进行排序。默认情况下,如果是方法作为列展示,那么列标题名会是该方法名,方法名中的下划线将以空格替代,并且每行内容的输出都将以字符串的形式展示。

你可以通过在该方法上使用display()装饰器来改进它(polls/models.py),如下所示:

from django.contrib import admin

class Question(models.Model):
    # ...
    @admin.display(
        boolean=True,
        ordering="pub_date",
        description="最近发布",
    )
    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now

有关装饰器的更多内容,可以通过官方文档进行获取。

再次编辑polls/admin.py文件,并对问题更改列表页面进行改进:使用列表过滤器进行过滤。在QuestionAdmin中添加以下行:

list_filter = ["pub_date"]

它增加了一个“过滤器”侧边栏,让人们可以通过发布日期字段过滤问题列表:

所显示的过滤器类型取决于要过滤的字段类型。因为pub_date是一个DateTimeField,Django知道给出适当的过滤器选项:“任意日期”、“今天”、“过去7天”、“本月”、“今年”。

一切良好,让我们添加一些搜索功能:

search_fields = ["question_text"]

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

自定义管理外观

显然,在每个管理页面的顶部放置“Django管理”是不合适的,它只是占位符文本,应用程序管理页面应该显示该应用程序的名称,你可以使用Django的模板系统来改变它。Django管理是由Django自己提供的,它的接口使用Django自己的模板系统。

自定义项目的模板

在项目目录(包含manage.py的目录)中创建一个templates文件夹。模板可以存放于Django可以访问的文件系统的任何地方,然而,将模板保留在项目中是一个很好的习惯。

打开你的配置文件(mysite/settings.py)然后在TEMPLATES配置项中添加DIRS配置项:

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模板时要检查的文件系统目录列表,这是一条搜索路径。

现在在templates目录中创建一个名为admin的文件夹,并从Django自身源代码默的Django admin模板目录(Django/contrib/admin/templates)中复制模板admin/base_site.html到该目录中。

Django的源文件在哪里?

如果你很难在你的系统中找到Django的源文件,可以运行以下命令:

python -c "import django; print(django.__path__)"

然后,编辑文件,将{{ site header|default: (‘Django administration’) }}(包括花括号)替换为你自己网站的名称。更改后类似于下面代码的样子:

{% block title %}{% if subtitle %}{{ subtitle }} | {% endif %}{{ title }} | 投票管理{% endblock %}

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

我们使用这种方法来覆盖模板。在实际的项目中,你可能会使用django.contrib.admin.AdminSite.site_header属性来更容易地进行这种特定的自定义。这个模板文件包含很多文本,比如{% block branding %}{{ title }}{%{{标签是Django模板语言的一部分。当Django呈现admin/base_site.html时,这个模板语言将被求值以生成最终的HTML页面。

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

欢迎关注我的公众号

  • 25
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值