乐趣区

关于python: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 笔记。

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

如果想获取更多相干文章,可扫码关注浏览:

退出移动版