Python / 21 Django 自带的 Admin 管理工具

Django 自带的 Admin 管理工具

Django 给我们提供了一个内置的完整功能的管理页面。在这个管理页面,我们可以对实现的模型对象进行完整的增删改查操作,足以满足我们的日常需求,接下来开始进入这个管理工具的使用。

1. 初识 Admin Web

首先 Django 工程中默认自带 Admin 管理工具并作为内置应用在 settings.py 中的 INSTALLED_APPS 上进行了注册:

INSTALLED_APPS = [
    # 注册 admin 应用
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # 注册应用
    'hello_app'
]

接下来为了能访问到这个后台管理的 Web 页面,Django 在初始化项目时,自动为我们添加了这个 Web 页面的相关的路由信息:

# first_django_app/urls.py

urlpatterns = [
    # admin后台管理页面的地址
    url('admin/', admin.site.urls),
]

注意:如果不想要这个自带的后台管理系统,也可以直接删除这个 URLconf 配置即可。

我们启动测试的 Django 工程,然后手动访问这个 admin 后台,具体操作如下:

(django-manual) [root@server first_django_app]# python manage.py runserver 0.0.0.0:8888
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.

April 12, 2020 - 15:11:39
Django version 2.2.11, using settings 'first_django_app.settings'
Starting development server at http://0.0.0.0:8888/
Quit the server with CONTROL-C.

注意:对于上面出现的告警信息是因为我们没有做数据库的迁移。在 Django 中为我们设计了一些内部的表,比如用来保存 admin 管理工具账号的表,比如保存 session 的表等。只需要使用 Django 提供的 makemigrationsmigrate 命令即可:

(django-manual) [root@server first_django_app]# python manage.py makemigrations
Migrations for 'hello_app':
  hello_app/migrations/0002_auto_20200412_1512.py
    - Alter field vip_level on member
(django-manual) [root@server first_django_app]# python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, hello_app, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying hello_app.0002_auto_20200412_1512... OK
  Applying sessions.0001_initial... OK

可以通过 Navicate 工具查看到 Django 给我们生成了 10 张表内部表,这 10 张表之间存在许多关联的地方。如下图所示:

图片描述

再次使用 runserver 命令启动 Django 工程时,就不会再有迁移相关的告警提示了。这个时候我们访问 admin/ 地址,就可以看到如下的登录页面。

图片描述

这里的登录账号和密码我们可以通过 Django 提供的 createsuperuser 命令完成:

(django-manual) [root@server first_django_app]# python manage.py createsuperuser
Username (leave blank to use 'root'): admin
Email address: 22@11.com
Password: 
Password (again): 
Superuser created successfully.

上面命令执行成功后,我们可以看到数据库的 auth_user 表中多出了一条用户信息的记录,正是我们上面设置的用户名和密码信息。

图片描述

使用这个刚创建的用户名和密码登录进入管理系统页面如下:

图片描述

在首页中,我们可以对用户和用户组进行管理,包括对表中数据的更新、修改和删除。如下是新增用户以及新增完成后的操作示例。完成新增完成后,还可以选择该条记录进行调整,直接影响的就是数据库中的 auth_user 表。

图片描述

图片描述
除了管理内置的表外,Django 的 admin 功能还可以管理我们定义的模型表,实现基本的增删改查操作。我们继续用前面的会员表和会员等级表进行实操。

hello_app/admin.py 文件中添加如下代码,将我们定义的模型注册到 admin 模块中:

from django.contrib import admin
from .models import Member, VIPLevel

# Register your models here.
admin.site.register([Member, VIPLevel])

重启 Django 工程,然后继续访问 admin 管理页面,让我们可以看到我们定义的模型出现在了管理页面上。而且我们还可以操作我们的模型,进行增删改查数据。

图片描述

注意:这里表中数据的展示方式是按照模型类中定义的 __str__ 魔法函数决定的。

图片描述

图片描述

这里可以看到 Member 表的关联表中数据,使用起来非常方便。

2. 深入 Admin Web

2.1 自定义模型管理页面

我们可以看到,默认 Admin 管理页面给我们提供的增删改查操作,页面的内容比较单一。如果我们想自定义管理页面的内容以及功能的时候,可以使用 ModelAdmin 类,它是模型在 Admin 界面中的表示形式,封装了模型的 Admin 功能和选项。通常,会将它们放在应用中的名为 admin.py 的文件里。

from django.contrib import admin
from .models import Member, VIPLevel

@admin.register(Member)
class MemberAdmin(admin.ModelAdmin):
    pass

@admin.register(VIPLevel)
class VIPLevelAdmin(admin.ModelAdmin):
    pass

上面这样的写法等价于我们使用默认的管理方式,和之前的 admin.site.register([Member, VIPLevel]) 注册函数功能一致,仅仅是表示注册。我们来看看 ModelAdmin 的常用属性值:

  • actions_on_top / actions_on_bottom:用来控制列表页按钮显示位置;
  • date_hierarchy:只可作用在 DateField 和 DateTimeField 上。设置后, 可以根据时间段, 去过滤数据;
  • empty_value_display:此属性会覆盖记录字段为空的默认显示值。 默认值为-(破折号);
  • exclude:排除新增/编辑页面需要显示的字段;
  • fields:指定新增、编辑页面要显示的字段;
  • fieldsets:设置 fieldsets 以控制管理页面的 “Add” 和 “Change” 按钮跳转页面的布局;
  • list_display:控制列表页要显示的字段;如果我们没有设置 list_display 属性,那么 admin 站点仅显示一列,显示 __str__() 的结果,这正是我们前面看到的现象;
  • list_display_links:指定哪些在列表页显示的字段上加链接;
  • list_editable:指定哪些字段可以直接在列表页编辑;
  • list_filter:指定列表页过滤字段;
  • list_per_page:指定列表页每页显示的记录数;
  • ordering:指定字段的排序,比如正序、倒叙等等。

我们使用 ModelAdmin 类来改造下前面的 Member 模型的展示页面,代码如下:

from django.contrib import admin
from .models import Member, VIPLevel

# Register your models here.

@admin.register(Member)
class MemberAdmin(admin.ModelAdmin):
    actions_on_top = False
    actions_on_bottom = True
    date_hierarchy = 'register_date'
    empty_value_display = '-empty-'
    list_display = ('name', 'age', 'city', 'sex', 'occupation', 'phone_num')
    list_editable = ('age', 'sex')
    list_filter = ('occupation', 'city')
    ordering = ['-age']
    list_per_page = 5

@admin.register(VIPLevel)
class VIPLevelAdmin(admin.ModelAdmin):
    pass

每个属性值对应的效果如下图所示:

图片描述

更多关于 ModelAdmin 类的属性及其用法,我们需要参看官方文档,那里有十分详细的属性说明以及代码演示。及时查看官方文档辅助学习 Django 是一个非常有效的学习手段,毕竟那里才是 Django 一切学习文档的来源地。

2.2 Admin 中的 actions

我们前面看到,Admin 中的 actions 是控制模型列表的动作,比如页面上批量更新操作等。来看如下的示例代码:

from django.contrib import admin
from .models import Member, VIPLevel

# Register your models here.
def make_men(modeladmin, request, queryset):
    queryset.update(sex=0)
make_men.short_description = "全部转成男性"

@admin.register(Member)
class MemberAdmin(admin.ModelAdmin):
    actions_on_top = False
    actions_on_bottom = True
    date_hierarchy = 'register_date'
    empty_value_display = '-empty-'
    list_display = ('name', 'age', 'city', 'sex', 'occupation', 'phone_num')
    list_editable = ('age', 'sex')
    list_filter = ('occupation', 'city')
    ordering = ['-age']
    list_per_page = 5
    actions = [make_men]

@admin.register(VIPLevel)
class VIPLevelAdmin(admin.ModelAdmin):
    pass

我们自定义了一个 make_men() 方法,这个方法会作为 MemberAdmin 对象的一个 action 方法。然后给该方法添加 short_description 属性,最后将该方法添加到 ModelAdmin 对象的 actions 属性中去。这样在模型管理页面的 Action 栏会出现对应的标签,用于实现相应的动作,如下图所示:

图片描述

该 action 方法固定有三个参数:

  • 当前的 ModelAdmin 对象实例;
  • 一个 HttpRequest 实例,用于表示当前的 HTTP 请求;
  • 用户选中记录对应组成的 QuerySet 实例;

选择我们定义的 action 方法,然后点击 Go 按钮,就可以将所有选中记录的性别改为男性。操作结果如下:

图片描述

我们可以看到每个模型管理页面的 Action 栏的下拉框都会有一个默认的动作,就是删除选中的记录。如果我们不想要这个动作选项,可以在 admin.py 中加上admin.site.disable_action 代码即可。如果有的模型想要有这个选项,而另一个模型不想要这个选项,则可以使用如下的方式完成需求:

# 关闭本应用模型的删除选中动作选项
admin.site.disable_action('delete_selected')

# Member模型管理页面不会有删除选中动作选项
@admin.register(Member)
class MemberAdmin(admin.ModelAdmin):
    ...

# VIPLevel模型管理页面则会有删除选中动作选项
class VIPLevelAdmin(admin.ModelAdmin):
    actions = ['delete_selected', 'a_third_action']
    ...

图片描述

最后,如果直接不想要这个 Action 栏,我们直接给模型对应的 ModelAdmin 对象设置 action = None 即可,结果如下:

图片描述

3. 小结

这里我们简单的介绍了下 Django 自带的 Admin 管理页面,同时通过配置一行代码可以管理我们定义的模型。此外,为了能够自定义管理页面的内容以及相关的功能,学习了 Django 提供的 ModelAdmin 类并进行了实操演示。不过,尽管 Django 为我们提供了这么多功能,在大多数场景下还是显得非常简陋和不友好,还需要引入第三方的插件来丰富和美化我们的后台管理功能。在后面的第三方模块小节中我们会介绍一个第三方的 Django 后台管理系统—xadmin,然后会在该管理系统的基础上进行实战开发。