我们将继续使用web-poll 应用程序,并将专注于自定义Django的自动生成的管理站点,
自定义管理表单
通过使用admin.site.register(Question)注册Question model,Django能够构造一个默认的表单表示法。通常,您需要定制admin表单的外观和工作方式。您将通过告诉Django在登记客体时所需要的选项来做到这一点。
让我们通过重新排序编辑表单中的字段来了解它是如何工作的。将admin.site.register(Question) 行替换为:
polls/admin.py
from django.contrib import admin
from .models import Question
# Register your models here.
class QuestionAdmin(admin.ModelAdmin):
fields = ['pub_date', 'question_text']
admin.site.register(Question, QuestionAdmin)
您将遵循这个模式——创建一个model admin类,然后将其作为第二个参数传递给admin.site.register()——任何时候您需要更改 models 的 管理选项。
上面的这个特殊的变化使得“发布日期”出现在“Question”领域之前:
这对于只有两个字段来说并不令人印象深刻,但是对于有几十个字段的管理表单来说,选择一个直观的顺序是一个重要的可用性细节。
说到有几十个字段的表单,您可能想要将表单拆分为fieldset:
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)
fieldset中的每个元组的第一个元素是fieldset的标题。这是我们现在的样子:
添加相关对象
好的,我们有一个Question管理页面,但是一个问题有多个Chioce,而管理页面没有显示选项。
然而。
有两种方法可以解决这个问题。第一种方法是在管理员中注册Chioce,就像我们对Question所做的那样。这很简单:
polls/admin.py
from django.contrib import admin
from .models import Choice, Question
# ...
admin.site.register(Choice)
现在“选择”是Django管理员的一个可用选项。“添加选择”的形式是这样的:
在这种形式中,“Question”字段是一个包含数据库中所有问题的选择框。Django知道一个外键应该在admin中作为一个 box 来表示。在我们的例子中,只有一个问题存在。
还要注意在“Question”旁边的“添加另一个”链接。“每一个与另一个有外键关系的物体都是免费的。。当你点击“添加另一个”时,你会得到一个带有“添加问题”表单的弹出窗口。如果你在那个窗口中添加一个问题并点击“保存”,Django将把这个问题保存到数据库中,并在你所看到的 “添加选择” 表单中动态添加它作为选择的选项。
但是,实际上,这是一种将选择对象添加到系统的低效方法。如果你在创建Question对象时可以直接添加一些选项,那就更好了。让我们实现它。
取消Choice模型的register()调用。然后,编辑Question注册码以阅读:
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个选择提供足够的字段。”
加载“添加问题”页面来查看它的外观:
它的工作原理是这样的:有三个插槽用于相关的选择——由额外的指定——每次您返回到已经创建的对象的“更改”页面时,您将得到另外三个额外的插槽。
在这三个当前位置的末尾,你会发现一个“添加另一个选择”链接。如果你点击它,就会添加一个新的槽。如果你想删除添加的槽,你可以点击添加槽的右上角的X。请注意,您不能删除原来的三个槽。这张图片显示了一个额外的插槽:
不过,一个小问题。它需要大量的屏幕空间来显示输入相关选择对象的所有字段。出于这个原因,Django提供了一种显示内联相关对象的表格方式; 您只需要更改 ChoiceInline声明即可阅读:
polls/admin.py
class ChoiceInline(admin.TabularInline):
#...
有了这种TabularInline(而不是StackedInline),相关的对象以一种更紧凑的、基于表格的格式显示:
注意这里有一个额外的“删除”?“列”,允许删除使用“添加另一个选择”按钮和已经保存的行。
自定义管理更改列表
现在问题管理页面看起来不错,让我们对“变更列表”页面进行一些调整——这个页面显示了系统中所有的问题。
以下是它的样子:
在默认情况下,Django显示每个物体的str()。但有时,如果我们能显示单独的字段,会更有帮助。要做到这一点,请使用list_display admin选项,它是字段名的元组,用于显示对象的更改列表页面:
polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
# ...
list_display = ('question_text', 'pub_date', 'was_published_recently')
Now the question change list page looks like this:
您可以单击栏目标题来对这些值进行排序——除了 was_published_recently最近的报头之外,因为不支持任意方法的输出排序。还要注意,最近 was_published_recently的栏目标题是,默认情况下,这个方法的名称(用空格代替下划线),并且每一行都包含输出的字符串表示。
您可以通过提供该方法(在polls/models.py)中一些属性来改进它,如下所列
polls/models.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?'
For more information on these method properties, see list_display
.
Edit your polls/admin.py
file again and add an improvement to the Question
change list page: filters using thelist_filter
. Add the following line to QuestionAdmin
:
list_filter = ['pub_date']
这增加了一个“过滤器”的侧边栏,让人们可以通过pub_date字段来过滤更改列表:
这是一个很好的发展。让我们添加一些搜索功能:
search_fields = ['question_text']
这就在变更列表的顶部添加了一个搜索框。当有人输入搜索词时,Django将搜索question_text字段。您可以使用尽可能多的字段——尽管因为它在后台使用了类似的查询,所以将搜索字段的数量限制为一个合理的数字将使您的数据库更容易进行搜索。
现在也是一个值得注意的好时机,更改列表会给你免费分页。默认情况下,每页显示100个项目。更改列表分页、搜索框、过滤器、日期层次结构和列-头-排序都像您认为的那样工作。
自定义管理外观和感觉
显然,在每个管理页面的顶部有“Django管理”是很荒谬的。它只是占位符文本。
不过,使用Django的模板系统很容易改变。Django admin 是由Django本身提供的,它的接口使用Django自己的模板系统
定制您的项目模板
在项目目录中创建一个templates目录(其中包含managepy)。模板可以在Django可以访问的文件系统的任何地方生存。(Django运行的是您的服务器运行的任何用户。)然而,将模板保留在项目中是一个很好的惯例。
打开你的设置文件(mysite/settings。记住)并在模板设置中添加一个DIRS选项:
mysite/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',
],
},
},
]
DIRS是一个文件系统目录列表,用于检查何时加载Django模板;这是一个搜索路径
组织模板
就像静态文件一样,我们可以把所有的模板放在一起,在一个大的模板目录中,并且它可以很好地工作。但是,属于特定应用程序的模板应该放在该应用程序的模板目录(例如polls/templates)而不是项目的(templates)中。
在 templates 目录下添加 admin 目录, 然后复制从默认django admin 模板(django/contrib/admin/templates)中模板 拷贝到 admin/base_site.html
Django源文件在哪里?
如果您很难找到Django源文件位于您的系统上的位置,请运行以下命令:
python -c "import django; print(django.__path__)"