一. 前言
注意
在开始教程之前,为了更合理地拆分功能模块,我把之前创建的名称为 front_blog 的 APP 改为了 front,admin_blog 改为了 article,希望小伙伴也能改一下,抱歉了。
在上一篇博文 Django 个人博客搭建(2)-编写视图 中,主要讲述了如何在 Django 中编写视图,粗略地利用 django 自带的 admin 添加了一篇文章。接下来,将讲述如何定制 admin 以及一些使用技巧。
二. 定制 admin
1. 侧边栏优化
修改模型名称
运行 Django 项目,进入 admin。发现侧边栏的 App 名称和模型名称都为英文,需要将其改为中文。
- 修改 article/models.py,为每一个模型类添加
Meta
的 class 属性。verbose_name
表示后台界面模型显示名称,verbose_name_plural
表示复数形式名称,中文不分单复数,其值和verbose_name
相同即可。具体代码如下:
from django.conf import settings
from django.db import models
# 文章模型类
class Article(models.Model):
id = models.BigAutoField(primary_key=True) # 主键
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name="作者") # 与自带的auth.user关联
label = models.ManyToManyField('Label', verbose_name="标签") # Label和Article为多对多关系
title = models.CharField(max_length=100, verbose_name="标题") # 标题
content = models.TextField(max_length=100000, verbose_name="内容") # 内容
summary = models.CharField(blank=True, max_length=200, verbose_name="摘要") # 摘要
gmt_created = models.DateTimeField(blank=True, null=True, auto_now_add=True) # 创建时间
gmt_modified = models.DateTimeField(blank=True, null=True, auto_now=True) # 修改时间
class Meta:
verbose_name = '文章' # 后台模型显示名称
verbose_name_plural = '文章' # 后台模型复数显示名称
# 分类模型类
class Category(models.Model):
id = models.BigAutoField(primary_key=True)
category_name = models.CharField(max_length=32, verbose_name="分类名称") # 分类名
gmt_created = models.DateTimeField(blank=True, null=True, auto_now_add=True) # auto_now_add为添加时的时间,更新对象时不会有变动。
gmt_modified = models.DateTimeField(blank=True, null=True, auto_now=True) # auto_now无论是你添加还是修改对象,时间为你添加或者修改的时间。
class Meta:
verbose_name = '分类'
verbose_name_plural = '分类'
# 标签模型类
class Label(models.Model):
id = models.BigAutoField(primary_key=True, verbose_name="标签名称")
label_name = models.CharField(max_length=32) # 标签名
category = models.ManyToManyField('Category') # Label和Category是多对多关系
gmt_created = models.DateTimeField(blank=True, null=True, auto_now_add=True) # auto_now_add为添加时的时间,更新对象时不会有变动。
gmt_modified = models.DateTimeField(blank=True, null=True, auto_now=True) # auto_now无论是你添加还是修改对象,时间为你添加或者修改的时间。
class Meta:
verbose_name = '标签'
verbose_name_plural = '标签'
- 修改完之后刷新后台界面,查看具体效果。
修改 App 名称
-
修改模型显示名称之后,我们发现 app 名称仍然为英文 Article,需要将其改为中文。
-
进入 article/init.py,设置默认 app_config,重新定义
AppConfig
,加入verbose_name
属性,verbose_name
的值即为后台 app 显示名称,如下。
from django.apps import AppConfig
import os
default_app_config = 'article.ArticleConfig'
# 获取apps所在文件夹名字,如果文件夹名字修改,这里可以动态调整
def get_current_app_name(_file):
return os.path.split(os.path.dirname(_file))[-1]
class ArticleConfig(AppConfig):
# 这里apps所在文件夹名字直接固定,如果更改则也需要调整
# name = 'article'
name = get_current_app_name(__file__) # 这里的结果是:article
verbose_name = '文章管理'
- 修改完之后刷新后台界面,操作无误的话可以看到 APP 名称也变成中文了。
2. 表单优化
表单字段显示优化
-
点击文章管理/文章,然后点击之前添加的那篇文章,发现表单名称都为英文。
-
将其修改为自定义中文字段,修改 article/models.py,为每一个字段添加
verbose_name
属性,该属性的值即为后台表单中显示的字段名称。例如我们将Article
模型类中的tile
字段添加属性verbose_name="标签"
,则它将在后台表单中显示为标签
。代码如下。
# Create your models here.
from django.conf import settings
from django.db import models
# 文章模型类
class Article(models.Model):
id = models.BigAutoField(primary_key=True) # 主键
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name="作者") # 与自带的auth.user关联
label = models.ManyToManyField('Label', verbose_name="标签") # Label和Article为多对多关系
title = models.CharField(max_length=100, verbose_name="标题") # 标题
content = models.TextField(max_length=100000, verbose_name="内容") # 内容
summary = models.CharField(blank=True, max_length=200, verbose_name="摘要") # 摘要
gmt_created = models.DateTimeField(blank=True, null=True, auto_now_add=True) # 创建时间
gmt_modified = models.DateTimeField(blank=True, null=True, auto_now=True) # 修改时间
class Meta:
verbose_name = '文章'
verbose_name_plural = '文章'
# 分类模型类
class Category(models.Model):
id = models.BigAutoField(primary_key=True)
category_name = models.CharField(max_length=32, verbose_name="分类名称") # 分类名
gmt_created = models.DateTimeField(blank=True, null=True, auto_now_add=True) # auto_now_add为添加时的时间,更新对象时不会有变动。
gmt_modified = models.DateTimeField(blank=True, null=True, auto_now=True) # auto_now无论是你添加还是修改对象,时间为你添加或者修改的时间。
class Meta:
verbose_name = '分类'
verbose_name_plural = '分类'
# 标签模型类
class Label(models.Model):
id = models.BigAutoField(primary_key=True, verbose_name="标签名称")
label_name = models.CharField(max_length=32) # 标签名
category = models.ManyToManyField('Category') # Label和Category是多对多关系
gmt_created = models.DateTimeField(blank=True, null=True, auto_now_add=True) # auto_now_add为添加时的时间,更新对象时不会有变动。
gmt_modified = models.DateTimeField(blank=True, null=True, auto_now=True) # auto_now无论是你添加还是修改对象,时间为你添加或者修改的时间。
class Meta:
verbose_name = '标签'
verbose_name_plural = '标签'
- 点击文章列表中的文章,进入修改页面,检验修改效果。
列表字段显示优化
之前我们在 artilce/admin.py 中利用了 admin.site.register 注册模型类,但这只能够简单地对数据进行管理。
from django.contrib import admin
# 导入模型类
from article.models import Article, Category, Label
# 注册
admin.site.register(Article)
admin.site.register(Category)
admin.site.register(Label)
文章列表并不能显示标题和作者等信息。因此我们需要借助 Django 为我们提供的 ModelAdmin 进行深度定制,ModelAdmin 类是一个可以继承的基类,它负责 admin 页面里的数据展示。
-
修改 artilce/admin.py,新建 ArticleAdmin 类,在其中写入 list_display ,list_display 的值是一个元祖,它表明哪些字段将在列表中显示。例如,将 ArticleAdmin 中的 list_display 值设为
('title', 'user', 'gmt_created')
,如下:注意:不要忘记把 Article 类和 ArticleAdmin 类通过
admin.site.register(Article, ArticleAdmin)
注册到 admin 站点中
from django.contrib import admin
# 导入模型类
from article.models import Article, Category, Label
class ArticleAdmin(admin.ModelAdmin):
list_display = ('title', 'user', 'gmt_created')
# 注册
admin.site.register(Article, ArticleAdmin)
admin.site.register(Category)
admin.site.register(Label)
- 刷新后台界面,查看文章列表,观察效果。
列表多对多属性显示
那如果我们想在列表中显示多对多字段属性该怎么办,例如,在文章列表中,想要显示标签属性(文章和标签是 ManyToMany 多对多关系)
-
显示多对多关系字段,需要重新定义显示函数,利用数据库 ORM 方法返回关联的对象中所需要显示的字段。
-
修改 artilce/admin.py,在 list_display 中加入自定义字段
标签
,定义并实现标签
函数,如下。注意:自定义字段名称与函数名称要一致。
from django.contrib import admin
# 导入模型类
from article.models import Article, Category, Label
class ArticleAdmin(admin.ModelAdmin):
# 显示的字段
list_display = ('title', 'user', '标签', 'gmt_created')
# 定义标签显示
def 标签(self, obj):
return [l.label_name for l in obj.label.all()] # 返回与Article关联的Label的label_name字段属性的值
filter_horizontal = ('label',) # 表示对label属性进行过滤
# 注册
admin.site.register(Article, ArticleAdmin)
admin.site.register(Category)
admin.site.register(Label)
- 刷新后台界面,检查修改结果。
表单多对多字段显示
-
进入添加标签页面,我们发现分类显示并未显示分类名称。
-
为了能够显示分类名称,需要修改 article/models.py 文件,在 Category 模型类中重写
__str__
方法,返回分类名称 category_name 属性。同时为了能在添加文章时显示标签名称,也在 Lable 模型类中重写__str__
方法。具体代码如下:
from django.conf import settings
from django.db import models
# 文章模型类
class Article(models.Model):
id = models.BigAutoField(primary_key=True) # 主键
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name="作者") # 与自带的auth.user关联
label = models.ManyToManyField('Label', verbose_name="标签") # Label和Article为多对多关系
title = models.CharField(max_length=100, verbose_name="标题") # 标题
content = models.TextField(max_length=100000, verbose_name="内容") # 内容
summary = models.CharField(blank=True, max_length=200, verbose_name="摘要") # 摘要
gmt_created = models.DateTimeField(blank=True, null=True, auto_now_add=True) # 创建时间
gmt_modified = models.DateTimeField(blank=True, null=True, auto_now=True) # 修改时间
class Meta:
verbose_name = '文章'
verbose_name_plural = '文章'
def __str__(self):
return self.title
# 分类模型类
class Category(models.Model):
id = models.BigAutoField(primary_key=True)
category_name = models.CharField(max_length=32, verbose_name="分类名称") # 分类名
gmt_created = models.DateTimeField(blank=True, null=True, auto_now_add=True) # auto_now_add为添加时的时间,更新对象时不会有变动。
gmt_modified = models.DateTimeField(blank=True, null=True, auto_now=True) # auto_now无论是你添加还是修改对象,时间为你添加或者修改的时间。
class Meta:
verbose_name = '分类'
verbose_name_plural = '分类'
def __str__(self):
return self.category_name # 在后台表单中显示分类名
# 标签模型类
class Label(models.Model):
id = models.BigAutoField(primary_key=True)
label_name = models.CharField(max_length=32, verbose_name="标签名称") # 标签名
category = models.ManyToManyField('Category', verbose_name="分类") # Label和Category是多对多关系
gmt_created = models.DateTimeField(blank=True, null=True, auto_now_add=True) # auto_now_add为添加时的时间,更新对象时不会有变动。
gmt_modified = models.DateTimeField(blank=True, null=True, auto_now=True) # auto_now无论是你添加还是修改对象,时间为你添加或者修改的时间。
class Meta:
verbose_name = '标签'
verbose_name_plural = '标签'
def __str__(self):
return self.label_name
- 刷新后台页面,进入添加标签页面,不出意外就能显示出分类名称了。
3. 常用功能集成
添加搜索栏和分页
后台中我们有时候需要查询参数,默认是没有开启搜索功能的,我们需要在 article/admin.py 中加入 search_fields = ('title', 'label__label_name')
来开启搜索功能。
search_fields
中的参数是模型类中的字段名,该字段名可以用来进行关键字查询。跨表查询类似于 django 的数据库 ORM 关系,在这里先不细说。
想要了解 Django 自带的 ORM 数据库 API 的可以查看我的另外一篇博客 Django 数据库常用 ORM 方法
同时加入分页参数 list_per_page
,即每页显示条数。具体代码如下:
from django.contrib import admin
# 导入模型类
from article.models import Article, Category, Label
class ArticleAdmin(admin.ModelAdmin):
# 显示的字段
list_display = ('title', 'user', 'show_labels', 'gmt_created', 'gmt_modified')
# 定义标签显示
def show_labels(self, obj):
return [l.label_name for l in obj.label.all()] # 返回与Article关联的Label的label_name字段属性的值
show_labels.short_description = "标签"
filter_horizontal = ('label',) # 表示对label属性进行过滤
search_fields = ('title', 'label__label_name') # 可搜索属性
list_per_page = 10 # 每页条数
class LabelAdmin(admin.ModelAdmin):
list_display = ('label_name', 'show_categories', 'gmt_created', 'gmt_modified') # 显示的字段
def show_categories(self, obj):
return [c.category_name for c in obj.category.all()]
show_categories.short_description = "分类"
filter_horizontal = ('category',) # 表示对label属性进行过滤
search_fields = ('label_name', 'category__category_name') # 可搜索属性
list_per_page = 10
class CategoryAdmin(admin.ModelAdmin):
# 显示的字段
list_display = ('category_name', 'gmt_created', 'gmt_modified')
list_per_page = 10
# 注册
admin.site.register(Article, ArticleAdmin)
admin.site.register(Category, CategoryAdmin)
admin.site.register(Label, LabelAdmin)
- 修改完之后,刷新后台界面,测试搜索功能。
Django 自带的 admin 还有很多强大的功能,在这里不再一一叙述了,小伙伴们可以自行钻研一波。下一篇将讲述如何编辑博客主页视图和页面显示。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于