Django快速入门——投票程序(7) 自定义后台

Python
216
0
0
2024-01-07
标签   Django

7. 自定义后台

自定义表单

通过admin.site.register(Question)注册Question模型,Django会创建默认的表单在后台显示。但有时需要自定义后台的显示,可以通过继承admin.ModelAdmin实现:

# 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)

fields定义了显示的内容。

如果表单字段很多,你可能想将它们分成不同部分:

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)

添加关联的对象

一个问题有多个选项,但后台却没有显示选项。有两个方法可以解决这个问题。一是像注册Question一样,注册Choice。

from django.contrib import admin

from .models import Choice, Question

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

现在可以看到选项,但是现在只能逐个创建选项并关联问题。

我们想要在创建问题时直接添加很多个选项:将polls/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=3)。

不过,现在选项占用的区域太大了。Django 提供了一种表格式的单行显示关联对象的方法。要使用它,只需按如下形式修改 ChoiceInline 声明:

class ChoiceInline(admin.TabularInline):
    ...

通过 TabularInline (替代 StackedInline ),关联对象以一种表格式的方式展示,显得更加紧凑。

自定义后台更改列表

现在投票的后台页看起来很不错,让我们对问题列表页面进行一些调整——改成一个能展示系统中所有投票的页面。默认情况下,Django 显示每个对象的 str() 返回的值。但有时如果我们能够显示单个字段,它会更有帮助。为此,使用 list_display属性,它是一个包含要显示的字段名的元组,在更改列表页中以列的形式展示这个对象:

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

另外,让我们把 教程第 2 部分 中的 was_published_recently() 方法也加上:

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

你可以通过在该方法上(在 polls/models.py 中)使用 display() 装饰器来改进:

from django.db import models
from django.contrib import admin
from django.utils import timezone
import datetime


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField("date published")

    def __str__(self):
        return self.question_text

    @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

接下来我们添加一个过滤器。编辑文件 polls/admin.py,将以下代码添加至 QuestionAdmin: list_filter = ["pub_date"]

这样做添加了一个“过滤器”侧边栏,允许人们以 pub_date 字段来过滤列表:

让我们再添加搜索功能: search_fields = ["question_text"]

在列表的顶部有了一个搜索框。当输入待搜项时,Django 将搜索 question_text 字段。(你可以使用任意多的字段)

说明

完整的教程可以前往官网:https://docs.djangoproject.com/zh-hans/4.2/intro/ 本教程省略了一些内容,如第5部分的测试,第8部分的扩展。

相关的代码:https://github.com/liufei65536/django_project