本文首发于公众号:Hunter后端

原文链接:Django笔记三十五之admin后台界面介绍

这一篇介绍一下 Django 的后台界面使用。

Django 自带了一套后台管理界面,可用于我们直接操作数据库数据,本篇笔记目录如下:

  1. 创建后台账号以及登录操作
  2. 注册后台显示的数据表
  3. 列表字段的显示操作
  4. 字段值的修改操作
  5. 列表页的执行操作

1、创建后台账号以及登录操作

首先我们需要创建一个可以访问后台的账号,以下命令在系统的根目录下进行:

python3 manage.py createsuperuser

然后他会提示我们输入账号的名称,邮箱以及两遍密码用于确认。

Username (leave blank to use 'hunter'): admin
Email address: xxxx@qq.com
Password:
Password (again):

在这个过程中,如果我们输入的密码少于8位或者过于简单,他会给我们提示说密码过于简单等,可以设置复杂点的,也可以直接确认。

创建好账号密码后,运行我们的系统:

python3 manage.py runserver 0:9898

然后就可以在浏览器里访问我们的后台系统了:

http://localhost:9898/admin

在下面的图里输入账号密码就可以进入系统了:

这里需要注意一点的是,如果你是按照我们的笔记一路操作过来,在前面我们的用户登录限制里可能限制了 login 和 register 接口才允许不登录,那么我们在相应的验证中间件里可以简单做一下操作:

class AuthMiddleware:

    def __init__(self, get_response):
self.get_response = get_response def __call__(self, request):
path = request.path # url 路径为 /users/register 和 /users/login 的接口不需要进行判断验证
if path not in [
"/users/register",
"/users/login",
]:
if path.startswith("/admin"):
return self.get_response(request)
session = request.session
if not session.get("username"):
return JsonResponse({"code": -1, "msg": "not login"}, status=401)
response = self.get_response(request)
return response

这里我们将 /admin 开头的接口都设置为了不需要登录验证。

2、注册后台显示的数据表

输入账号密码登录后台系统后,如果之前没有做过后台注册的相关操作的话,可能只会看到 Django 系统自带的 Users 和 Groups 表,它们是默认在后台显示的。

如果你点击进入 Users 表,可以看到我们刚刚创建的这个用于登录的管理员账号 admin。

如果我们想要使得我们创建的其他表也在后台显示,则需要手动去注册一下。

注册的流程很简单,我们这里以 blog 这个 application 为例,修改 blog/admin.py,对于需要显示的表,我们直接使用 admin.site.register() 操作,即可在后台显示,比如:

# blog/admin.py
from django.contrib import admin
from blog.models import Blog admin.site.register(Blog)

重启系统后,就可以看到多了一个 Blog 的 application 以及其下的 Blog 表了。

再点击进入表,可以看到一条条 Blog 表里的数据了,但是表的字段在列表页都是被隐藏的,只有在点击进入单条数据详情页时,才会显示具体的字段值。

3、列表字段的显示操作

前面介绍了如何注册一个 model,使其在后台界面显示,但是有一个问题就是数据列表每条都只有一个字段表示,而没有每个字段的具体值显示,接下来我们就对具体字段值的显示做介绍。

首先,我们使用的 model 定义如下:

class Blog(models.Model):
PUBLISHED = 1
UNPUBLISHED = 0
PUBLISHED_STATUS = (
(PUBLISHED, "published"),
(UNPUBLISHED, "not_published"),
) name = models.CharField(max_length=100, unique=True)
tag_line = models.TextField()
char_count = models.IntegerField(verbose_name="文章字数", default=0)
is_published = models.BooleanField(choices=PUBLISHED_STATUS, default=UNPUBLISHED)
pub_datetime = models.DateTimeField(verbose_name="发布日期", null=True, default=None)

定义好后的 migration 相关操作可以自己去完成。

注册操作

前面介绍了 model 在后台显示的注册操作:

# blog/admin.py
from django.contrib import admin
from blog.models import Blog admin.site.register(Blog)

但是这种操作只能在后台显示列表信息,具体的字段信息不会在列表显示,如果要实现这种操作,我们需要进行另一种注册方式:

# blog/admin.py

from django.contrib import admin
from blog.models import Blog class BlogAdmin(admin.ModelAdmin):
pass admin.site.register(Blog, BlogAdmin)

接下来,我们的具体操作都会在 BlogAdmin 中实现。

列表显示字段

如果我们想要在列表中就显示数据的具体字段,比如 id, name,is_published,pub_datetime 三个字段,我们可以使用 list_display 属性:

class BlogAdmin(admin.ModelAdmin):
list_display = ("id", "name", "is_published", "pub_datetime")

重启系统后,就可以在列表看到相应的字段显示了:

注意:在这里,is_published 这里直接显示了该字段的用于显示的值,这个和之前介绍的 get_field_display() 的方式是一致的。

可以看到,这个列表的表头就是我们定义的 model 里的 verbose_name 的值,如果没有定义该属性,则会直接显示字段名。

数据格式化显示

可以注意到日期的显示并不利于直观的查看,所以可以对日期字段做一个格式化处理返回显示。

以下是对 model 的处理:

# blog/models.py

from django.contrib import admin

class Blog(models.Model):
# 字段在这里省略
pass @admin.display(description="发布时间")
def format_pub_datetime(self):
return self.pub_datetime.strftime("%Y-%m-%d %H:%M:%S")

以下是对 BlogAdmin 的处理:

class BlogAdmin(admin.ModelAdmin):
list_display = ("id", "name", "is_published", "format_pub_datetime")

这样在列表页就会多一列,表头为【发布时间】。

这里我们其实可以这样理解,我们对 Blog 这个 model 添加了一个名为 format_pub_datetime 的属性,这个属性用 admin.display() 作为装饰器,这个属性可以作为被 admin 的 list_display 使用作为列表的展示项。

在这里我们是直接对 pub_datetime 字段做格式化处理,当然也可以对非时间字段做其他的处理,主要看想要实现的效果。

注意: 这里还有需要注意的一点是,pub_datetime 字段是允许为 null 的,所以这里最好是做一下适配处理,比如说 return 的时候判断一下:

    @admin.display(description="发布时间")
def format_pub_datetime(self):
return self.pub_datetime.strftime("%Y-%m-%d %H:%M:%S") if self.pub_datetime else ""

上面这种方式是在 model 下定义的函数,我们也可以直接在 BlogAdmin 定义该函数操作:

class BlogAdmin(admin.ModelAdmin):
list_display = ("id", "name", "is_published", "char_count", "format_pub_datetime") @admin.display(description="发布时间")
def format_pub_datetime(self, obj):
return obj.pub_datetime.strftime("%Y-%m-%d %H:%M:%S") if obj.pub_datetime else ""

列表数据排序

列表的数据默认是按照 id 的倒序排列返回的,如果想要按照其他字段排序返回,比如 char_count,可以使用 ordering 属性:

class BlogAdmin(admin.ModelAdmin):
list_display = ("id", "name", "is_published", "char_count", "format_pub_datetime")
ordering = ("char_count",)

如果是想要倒序排列,字段前加一个 - 即可:

ordering = ("-char_count",)

4、字段值的修改操作

如果我们想要在 admin 的页面修改数据的字段值,目前我们能做的操作就是点击每条数据前面的 id,他会进入这条数据的详情页,每个字段都是默认可修改的。

指定字段点击进入编辑页

我们也可以指定某个,或者某几个字段进入这条数据的详情页进行编辑,用到的属性是 list_display_links,这个属性的值默认是 id 主键字段,但如果我们想点击 id 和 name 字段的时候都进入详情页,可以如下操作:

class BlogAdmin(admin.ModelAdmin):
list_display = ("id", "name", "is_published", "format_pub_datetime")
list_display_links = ("id", "name",)

直接在列表页面修改字段值

如果某个字段是需要经常修改的,我们想要在列表页面就修改而不用进入数据的详情页,可以加上 list_editable 属性,比如我们直接在列表页修改 name 字段的值:

class BlogAdmin(admin.ModelAdmin):
list_display = ("id", "name", "is_published", "format_pub_datetime")
list_editable = ("name", )

需要注意的是,list_editable 和 list_display_links 这两个属性是相斥的,也就是说这两个的字段列表不能拥有同一个字段值。

详情页字段的显示与否

点击进入数据的编辑详情页,默认所有字段是可以修改的,如果想要某些字段在详情页显示或者不显示,可以使用 fields 和 exclude 属性,分别表示显示和不显示的字段。

显示 name 和 is_published 字段:

class BlogAdmin(admin.ModelAdmin):
list_display = ("id", "name", "is_published", "format_pub_datetime")
fields = ("name", "is_published")

隐藏 name 和 is_published 字段:

class BlogAdmin(admin.ModelAdmin):
list_display = ("id", "name", "is_published", "format_pub_datetime")
exclude = ("name", "is_published")

字段仅可读

有一些比较重要的字段,如果在详情页不希望能够被修改,可以使用 readonly_fields 属性,比如不希望 name 字段被修改:

class BlogAdmin(admin.ModelAdmin):
list_display = ("id", "name", "is_published", "format_pub_datetime")
readonly_fields = ("name",)

重启系统后,就可以在列表页看到 name 字段没有修改框,为仅可读状态了。

注意: 需要提醒的一点是,上面所有的添加字段属性的操作的值都需要是列表或者元组。

save_as 属性

save_as,这是一个在数据详情页保存时的属性,目前进入数据的详情页,右下角有三个按钮,左边的第一个是 save_and_add_another,意思是保存操作之后会自动进入新的页面,可用于创建数据。

当我们设置 save_as=True 之后:

class BlogAdmin(admin.ModelAdmin):
list_display = ("id", "name", "is_published", "char_count", "format_pub_datetime")
save_as = True

再看这三个按钮,第一个按钮就会变成 save as new,意思是在原数据上修改了之后,点击可以保存为一条新数据,原数据保持不变。

这个操作过程可以理解成我们前面一篇笔记中介绍如何新建一条数据的方式,就是在原数据上将 id 字段变成 None 然后进行 save 操作,就会在原数据的基础上创建一条新数据。

这个过程可以去看 Django笔记的第十八篇中自增的主键那一段。

5、列表页的执行操作

在列表页,目前仅有一个可供执行的操作,那就是选中 id 那一栏的数据之后,点击 action 旁边的下拉框,有一个 delete 操作,意思是删除选中的数据:

快速搜索过滤操作

对于某些值的种类比较少的数据,比如 is_published 字段,或者日期字段,想要实现快速搜索的操作,可以使用 list_filter 属性:

class BlogAdmin(admin.ModelAdmin):
list_display = ("id", "name", "is_published", "char_count", "format_pub_datetime")
list_filter = ("is_published", "pub_datetime")

重启系统后可以看到列表页面右侧出现了一个筛选列表:

对于非日期字段,这里有一些固定的日期的选择,对于其他字段,则是会列出所有字段值作为筛选项。

指定字段搜索

如果想要对某个或者某几个字段进行模糊搜索,可以使用 search_fields 属性,比如想要搜索 name 和 pub_datetime 字段:

class BlogAdmin(admin.ModelAdmin):
list_display = ("id", "name", "is_published", "char_count", "format_pub_datetime")
search_fields = ("name", "pub_datetime")

重启系统后,页面的左上角会出现一个搜索框,比如我们搜索 python,就会去查找 name 和 pub_datetime 字段中包含 python 的数据。

如果我们搜索的时候使用空格将搜索的关键字分隔开,那么系统会自动为我们进行 split() 操作,然后搜索,比如这里我们搜索的是 python 2021,那么系统转化的 sql 就会是:

where (name like '%python%' or pub_datetime like '%python%') and (name like '%2021%' or pub_datetime like '%2021%')

如果希望搜索的内容是一个整体,可以使用单引号或者双引号括起来 'python 2021'

日期分级筛选

前面介绍了一个快速搜索过滤的操作,这里针对于日期字段介绍一下另一种筛选过滤的方式,比如我们对 pub_datetime 字段进行操作:

class BlogAdmin(admin.ModelAdmin):
list_display = ("id", "name", "is_published", "char_count", "format_pub_datetime")
date_hierarchy = "pub_datetime"

重启系统后,可以在页面左上角看到 2021,2022,2023 几个年份,都是根据当前表里的数据统计出来的结果,然后点击进入相当于是进行了一次年份的筛选,在第二层页面继续点击选择则是一次新的筛选:

save_model()

前面在 Django笔记第十八篇中有介绍过一条数据的保存 save() 操作的继承处理,我们可以通过自定义一些逻辑使得数据在保存前进行一些操作,在这里,save_model() 的操作也可以提供同样的功能:

class BlogAdmin(admin.ModelAdmin):
list_display = ("id", "name", "is_published", "char_count", "format_pub_datetime") def save_model(self, request, obj, form, change):
print("do something")
super().save_model(request, obj, form, change)

actions 自定义执行任务

假设说我们想要实现一些批量执行的操作,比如选中列表页某些数据,将 is_published 字段批量更新成 True(即已发布),我们就可以用到 actions 来实现。

目前在页面的左上角有一个 action 和旁边的下拉框,系统实现了一个默认的函数逻辑,即删除选中项,我们可以来实现一个更新选中项的功能:

class BlogAdmin(admin.ModelAdmin):
list_display = ("id", "name", "is_published", "char_count", "format_pub_datetime") actions = ["make_published"] @admin.action(description="make queryset published")
def make_published(self, request, queryset):
queryset.update(is_published=True)

使用 admin.action 作为装饰器来装饰一个函数,然后将函数名称作为值放入 actions 列表中,在这里 queryset 参数即为页面选中的数据,它是一个 queryset 类型,所以这里可以直接进行 update() 操作。

如果想执行一些更深入的操作,我们也可以对 request 参数进行操作解析,它即为我们前端选中执行传过来的请求。

重启系统后,刷新页面,点开 action 旁边的下拉框,就可以看到我们定义的函数了,选中数据,点击旁边的 Go 按钮即可执行。

可以定义多个执行函数,记得添加到 actions 列表进行注册即可。

如果想获取更多后端相关文章,可扫码关注阅读:

Django笔记三十五之admin后台界面介绍的更多相关文章

  1. Django笔记三十二之session登录验证操作

    本文首发于公众号:Hunter后端 原文链接:Django笔记三十二之session登录验证操作 这一篇笔记将介绍 session 相关的内容,包括如何在系统中使用 session,以及利用 sess ...

  2. Django笔记二十五之数据库函数之日期函数

    本文首发于公众号:Hunter后端 原文链接:Django笔记二十五之数据库函数之日期函数 日期函数主要介绍两个大类,Extract() 和 Trunc() Extract() 函数作用是提取日期,比 ...

  3. Django笔记三十之log日志记录详解

    本文首发于公众号:Hunter后端 原文链接:Django笔记三十之log日志的记录详解 这一节介绍在 Django 系统里使用 logging 记录日志 以下是一个简单的 logging 模块示例, ...

  4. 【Unity 3D】学习笔记三十五:游戏实例——摄像机切换镜头

    摄像机切换镜头 在游戏中常常会切换摄像机来观察某一个游戏对象,能够说.在3D游戏开发中,摄像头的切换是不可或缺的. 这次我们学习总结下摄像机怎么切换镜头. 代码: private var Camera ...

  5. PHP学习笔记三十五【Try】

    <?php function AddUser($name) { if($name=="张三") { echo "add success"; return ...

  6. 论文阅读笔记三十五:R-FCN:Object Detection via Region-based Fully Convolutional Networks(CVPR2016)

    论文源址:https://arxiv.org/abs/1605.06409 开源代码:https://github.com/PureDiors/pytorch_RFCN 摘要 提出了基于区域的全卷积网 ...

  7. 第三百七十八节,Django+Xadmin打造上线标准的在线教育平台—django自带的admin后台管理介绍

    第三百七十八节,Django+Xadmin打造上线标准的在线教育平台—django自带的admin后台管理介绍 配置django的admin数据库管理后台 首先urls.py配置数据库后台路由映射,一 ...

  8. django笔记三之admin的管理

    django笔记三之admin的管理 设置自动admin应用 vim todos/settings.py INSTALLED_APPS = ( 'django.contrib.admin', 新版本已 ...

  9. Django笔记三十一之全局异常处理

    本文首发于公众号:Hunter后端 原文链接:Django笔记三十一之全局异常处理 这一篇笔记介绍 Django 的全局异常处理. 当我们在处理一个 request 请求时,会尽可能的对接口数据的格式 ...

  10. angular学习笔记(三十)-指令(6)-transclude()方法(又称linker()方法)-模拟ng-repeat指令

    在angular学习笔记(三十)-指令(4)-transclude文章的末尾提到了,如果在指令中需要反复使用被嵌套的那一坨,需要使用transclude()方法. 在angular学习笔记(三十)-指 ...

随机推荐

  1. manjaro日常使用之deepinTIM问题解决

    今天很高兴,因为我在我的manjaro+kde桌面上成功运行了deepinTIM.这样我离摆脱Windows使用的事业又更近了一步.众所周知,如果安装了kde桌面,deepinQQ的方案就无法运行,安 ...

  2. new Date()在IOS中的坑(转)

    原文地址:https://www.cnblogs.com/zjjDaily/p/8963327.html 第一次遇到,记录一下 要创建一个指定时间的new Date对象时,通常的做法是: new Da ...

  3. Go_day08

    Go的Io流 获取文件信息 //获取文件 fileinfo, err := os.Stat("./aa.txt")//相对绝对路径都可以 if err != nil { fmt.P ...

  4. Centos7安装nodejs(npm)

    执行命令: 设置yum安装源> curl --silent --location https://rpm.nodesource.com/setup_14.x | sudo bash (14是大的 ...

  5. 不同时间格式转换问题_python2

    def unix_to_cst(data): """2019-03-17 11:00:00 --> Sun, 17 Mar 2019 11:00:00 GMT+08 ...

  6. python计算三角形的三个边的边长,首先计算两个坐标点的距离

    # -*- coding:utf-8 -*- """ @author: 14931 @file: trianglearea.py @time: 2023/02/14 @d ...

  7. Hyperf安装

    转载网址: https://www.cnblogs.com/lyc94620/p/12821723.html

  8. 一起来试玩!在线可编程交互的实时音视频 Web SDK 入门教程

    在与开发者长期的沟通中,我们发现,尽管声网为开发者提供了丰富翔实的 SDK 技术文档,但对于初次接触声网 SDK 的开发者来说,在第一眼看到文档的时候,可能会被大量新概念和复杂的 API 接口淹没.S ...

  9. Unity Joint用法及案例

    目录 什么是Joint 有哪些Joint Joint计算原理 自由度配置 Axis与Anchor Limit与Spring Drive与Target Joint应用案例 车轮 旋转 悬挂系统 吊臂 旋 ...

  10. 接入HMS Core应用内支付服务过程中一些常见问题总结

    华为HMS Core应用内支付服务(In-App Purchases,IAP)为应用提供便捷的应用内支付体验和简便的接入流程.该服务支持客户端和服务端两种开发形式,具体可以参考官方文档. 往期文章:常 ...