来源引用网络知识与某站曹老师视频相互结合学习记录,仅供参考!
Django 内置 Admin 系统
Admin 后台系统也称为网站后台管理系统,主要对网站的信息进行管理,例如:文字、图片、影音和其他日常使用的文件的发布、更新、删除等操作,也包括功能信息的统计和管理,大部分还是对一些网站信息、业务系统信息进行管理,比如:用户信息、订单信息和访客信息等;简单来说,它是对网站数据库和文件进行快速操作和管理的系统,以使网页内容能够及时得到更新和调整;Django 内置的还有一套 Auth 权限系统。
Django 内置 Admin 系统初体验
介绍了解怎么进入系统登录以及创建用户;当一个网站上线之后,网站管理员通过网站后台系统对网站进行管理和维护;Django已内置Admin后台系统,在创建Django项目的时候,可以从项目的配置文件settings.py中看到项目已默认启用Admin后台系统。

Django项目创建成功之后会默认自动生成相关的Django项目配置文件,如若不需要自带的 Admin 系统可以自行删除,这样的话会减轻系统启动的负担;

查看"djangoProject"应用下的"urls.py"配置文件内容,可以看到"admin"对应的映射关系,已经定义了 Admin 系统的首页地址;
如何进入 Admin 系统
1、运行项目成功后,浏览器输入"http://127.0.0.1:8000/admin"即可打开 Admin 系统首页,默认跳转到 Admin 系统登录页面;

可以发现 Admin 登录页面是英文,而一般开发一个网站交付给客户的话,建议必须得是本地化中文的,所以可以加一个中文本地化的中间件来实现;
汉化处理,添加中间件
2、修改"djangoProject"应用下的"settings.py"项目配置文件内容中的"MIDDLEWARE"配置项,添加使用中文本地汉化中间件过滤设置语言,需特别注意有顺序要求,务必添加在第二个;
"""
Django settings for djangoProject project.
Generated by 'django-admin startproject' using Django 5.0.6.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.0/ref/settings/
"""
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-i01#=6cjknb()(5@p19olv+c2$tf7ez86)r%g!b&5(2&pdkfd0'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
"helloWorld.apps.HelloworldConfig",
"user.apps.UserConfig",
"order.apps.OrderConfig"
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
# 本地汉化使用中文(注意有顺序要求,务必添加在第二个)
'django.middleware.locale.LocaleMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'helloWorld.mymid.md1.Md1'
]
ROOT_URLCONF = 'djangoProject.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'helloWorld/templates', 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',
],
},
},
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [BASE_DIR / 'templates']
,
'APP_DIRS': True,
'OPTIONS': {
'environment': 'helloWorld.Jinja3.environment'
},
},
]
WSGI_APPLICATION = 'djangoProject.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'db_django6',
'USER': 'root',
'PASSWORD': '123',
'HOST': '192.168.88.145',
'PORT': '3306'
}
}
# Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/5.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/
STATIC_URL = 'static/'
# 设置静态资源文件集合
STATICFILES_DIRS = [BASE_DIR / "static", BASE_DIR / "helloWorld/images", BASE_DIR / "common"]
# 设置媒体路由
MEDIA_URL = 'media/'
# 设置media目录的完整路径
MEDIA_ROOT = BASE_DIR / 'media'
# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

3、重新运行项目,浏览器输入"http://127.0.0.1:8000/admin"测试验证,已经中文化成功;

4、Admin系统用户、权限、认证相关的表有6个(里面包含系统用户表,权限表,用户组,以及用户组权限关联表,用户和组关联表,用户权限关联表),可打开连接项目数据库表查看,其中auth_user是用来存后台管理员信息,默认里面是没有数据的;

创建超级管理员
可以通过 Python内置的manage.py的
createsuperuser命令来创建超级管理员的账号和密码;
5、PyCharm 工具(I)菜单栏选中"运行 manage.py 任务...(快捷键 Ctrl+Alt+R)",使用 Django5 manage.py 提供的内置命令,输入执行"createsuperuser"命令,根据提示信息分别自定义输入"用户名、邮箱、密码"等相关信息,最后成功创建超级管理员用户;

6、查看数据库表"auth_user",可以发现已经成功生成管理员数据信息了;

7、浏览器输入"http://127.0.0.1:8000/admin"打开Admin登录页面,输入刚才创建的用户名和密码,单击登录按钮登录 Admin 后台管理系统,成功登录后进入到系统管理主页,自行测试查看;

在Admin后台系统中可以看到,网页布局分为站点管理、认证和授权、用户和组,分别说明如下:
- 站点管理是整个Admin后台的主体页面,整个项目的App 所定义的模型都会在此页面显示;
- 认证和授权是Django内置的用户认证系统,包括用户信息、权限管理和用户组设置等功能;
- 用户和组是认证和授权所定义的模型,分别对应数据库 auth_user 和 auth_user_groups 表。
登录测试探索
Admin 管理员后台可自行进行添加修改用户等操作;

目前组还都是空的,因为还没有添加相关信息,还没有组,可以增加一个组,进行授权,建议自行测试探索。


Django 注册模型到 Admin 系统
在开发业务系统的时候,会定义很多的业务模型,可以把模型注册到Admin系统,让Admin系统帮忙维护这些模型;也就是在Admin后台自动给模型实现增删改查功能;注册模型到Admin系统有两个方式;
方式一,直接将模型注册到admin后台
8、以 BookTypeInfo 图书类别为例,打开"djangoProject"项目"helloWorld"应用下的"admin.py"配置文件,输入以下内容;
from django.contrib import admin
from helloWorld.models import BookTypeInfo
# Register your models here. 在这注册您的模型
# 方式一,将模型直接注册到admin后台
admin.site.register(BookTypeInfo)

9、打开 Admin 后台管理系统,刷新系统管理主页,可以在站点管理 HELLOWORLD 下看到"图书类别信息",点击进入图书类别信息里面可以进行新增、修改、删除等增删改查操作;

10、例如"添加"操作,它是模型直接对应到数据库里面,非常的方便,快速开发时使用这种方法就很有效率;

这种方式对于一般情况下的开发就基本已经满足了,如若除了增删改查操作,还需要其他特殊的设置需求,建议使用另一种方式;
方式二:自定义类,继承ModelAdmin
假如说"增删改查"等操作不满足需求,要额外"搜索字段、排序"等复杂一点的业务操作,建议使用此种方式;
11、以 BookInfo 图书类别为例,打开"djangoProject"项目"helloWorld"应用下的"admin.py"配置文件,输入以下内容,自定义类,继承ModelAdmin;
- class BookInfoAdmin(admin.ModelAdmin)--自定义类BookInfoAdmin,需要继承 ModelAdmin 父类;
- @admin.register(BookInfo)--需要在自定义类上加@admin.register(),里面添加需要注册哪个;
- 自定义类里面可以写一些精细化配置信息(包括每页大小、过滤条件、显示字段、查询字段、排序等等),具体可查看参考ModelAdmin 类源码;一般情况下默认设置即可满足,可根据业务需求自行精细化设置。
from django.contrib import admin
from helloWorld.models import BookTypeInfo, BookInfo
# Register your models here. 在这注册您的模型
# 方式一,将模型直接注册到admin后台
admin.site.register(BookTypeInfo)
# 方法二,自定义类,继承ModelAdmin
@admin.register(BookInfo)
class BookInfoAdmin(admin.ModelAdmin):
# 设置显示的字段,元组格式
list_display = ['id', 'bookName', 'price', 'publishDate', 'bookType']

可自行查看 ModelAdmin 类详情信息,对模型的增删改查操作做精细化的配置,包括显示字段,分页,可编辑字段,查询字段,排序等。

12、刷新系统管理主页,可以在站点管理 HELLOWORLD 下看到"图书信息",自行查看图书信息;

设置查询搜索
13、修改"djangoProject"项目"helloWorld"应用下的"admin.py"配置文件内容,设置查询;
from django.contrib import admin
from helloWorld.models import BookTypeInfo, BookInfo
# Register your models here. 在这注册您的模型
# 方式一,将模型直接注册到admin后台
admin.site.register(BookTypeInfo)
# 方法二,自定义类,继承ModelAdmin
@admin.register(BookInfo)
class BookInfoAdmin(admin.ModelAdmin):
# 设置显示的字段,元组格式
list_display = ['id', 'bookName', 'price', 'publishDate', 'bookType']
# 设置查询,也是元组格式
search_fields = ['bookName', 'publishDate']

14、刷新图书信息列表页面(建议重新运行项目),自行查看,可自行按输入查询条件搜索测试;

Django 内置 Admin 系统首页设置
在使用Django5的内置Admin系统时会发现一些默认的设置,并不符合实际的业务需求,需要自定义设置下;例如:模块项目管理这块标题,默认用了模块项目名称"Django 管理",非常不友好,大部分情况都是取名与工作相关的某某网站管理系统、某某企业名称之类的,建议设置人性化名称;

15、修改"djangoProject"项目"helloWorld"应用下的"admin.py"配置文件内容,设置网站标题和应用标题;
from django.contrib import admin
from helloWorld.models import BookTypeInfo, BookInfo
# Register your models here. 在这注册您的模型
# 方式一,将模型直接注册到admin后台
admin.site.register(BookTypeInfo)
# 方法二,自定义类,继承ModelAdmin
@admin.register(BookInfo)
class BookInfoAdmin(admin.ModelAdmin):
# 设置显示的字段,元组格式
list_display = ['id', 'bookName', 'price', 'publishDate', 'bookType']
# 设置查询,也是元组格式
search_fields = ['bookName', 'publishDate']
# 设置网站标题--浏览器标题(页面标题,<title></title>中的内容)
admin.site.site_title = '测试后台管理'
# 设置应用标题(首页标语)--首页主标题
admin.site.index_title = '图书管理模块'
# 设置网站页头--页眉标题(每个管理网页的页头都会出现的标题)
admin.site.site_header = 'Django测试网站管理系统'

16、修改"djangoProject"项目"helloWorld"应用下的"apps.py"配置文件内容,配置类中添加"verbose_name"字段数据信息项来更改设置子项目模块名称,如若有多个子项目,烦请自行设置各个子项目模块名称;
from django.apps import AppConfig
class HelloworldConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'helloWorld'
# 设置子项目模块名称
verbose_name = '测试网站图书管理'

17、重新运行项目,登录 Admin 系统,打开系统管理主页,自行测试查看;

django 自带后台中verbose_name 后面多个s的问题;如果verbose_name 后面没有_plural选项,则会在网站上类名后面自动拼接一个's';

Django 内置 Admin 系统二次开发
前面已经实现了 Admin 系统、模型注册、自定义设置;但是依然满足不了实际的业务开发需求;接下来,继续讲解更细致的 Admin 系统二次开发;
18、首先在Admin后台系统里新建一个普通管理员账号,鼠标单击认证和授权下面用户后面的"增加",自定义输入账号密码,注意需符合密码设置要求,长度至少 8 位,密码不能太常见、不能只包含数字、密码和用户名也不能太相似了等,例如,用户名:test02、密码:devdev02,单击保存按钮;

19、添加普通管理员用户成功,自定义设置相关权限后保存;

20、使用普通管理员用户 test02 登录系统,经测试验证,普通管理员用户 test02 能够登录成功;

设置不可编辑字段 get_readonly_fields()
在实际业务开发过程中,有时候一些敏感字段,不允许普通管理员修改;可以通过重写 ModelAdmin 的get_readonly_fields() 方法实现;
# 重写分类方法,设置只读字段
def get_readonly_fields(self, request, obj=None):
if request.user.is_superuser:
self.readonly_fields = []
else:
self.readonly_fields = ['bookName']
return self.readonly_fields
21、修改"djangoProject"项目"helloWorld"应用下的"admin.py"配置文件内容,重写 ModelAdmin 的 get_readonly_fields() 方法来设置不可编辑字段;
from django.contrib import admin
from helloWorld.models import BookTypeInfo, BookInfo
# Register your models here. 在这注册您的模型
# 方式一,将模型直接注册到admin后台
admin.site.register(BookTypeInfo)
# 方法二,自定义类,继承ModelAdmin
@admin.register(BookInfo)
class BookInfoAdmin(admin.ModelAdmin):
# 设置显示的字段,元组格式
list_display = ['id', 'bookName', 'price', 'publishDate', 'bookType']
# 设置查询,也是元组格式
search_fields = ['bookName', 'publishDate']
# 重写get_readonly_fields()方法,设置只读字段
def get_readonly_fields(self, request, obj=None):
# 增加判断,如果是超级管理员用户
if request.user.is_superuser:
# 设置所有字段都可编辑
self.readonly_fields = []
else:
# 不是超级管理员用户,设置某些字段为只读模式
self.readonly_fields = ['bookName', 'price', 'publishDate', 'bookType']
# 因为是get,所以最后得return返回
return self.readonly_fields
# 设置网站标题--浏览器标题(页面标题,<title></title>中的内容)
admin.site.site_title = '测试后台管理'
# 设置应用标题(首页标语)--首页主标题
admin.site.index_title = '图书管理模块'
# 设置网站页头--页眉标题(每个管理网页的页头都会出现的标题)
admin.site.site_header = 'Django测试网站管理系统'

22、使用普通管理员用户 test02 登录系统,打开修改图书信息页面,查看相关字段信息为不可编辑状态;

设置字段 label 名称为中文
打开修改图书信息页面,可以看到字段label名称是英文BookName,是因为目前还没有设置属性字段的verbose_name 值,可以在应用的 models.py 模型文件里,添加 verbose_name 配置项;
23、修改"djangoProject"项目"helloWorld"应用下的"models.py"模型文件内容,在BookInfo类里面的字段添加"verbose_name"设置项;
from django.db import models
# Create your models here.
class StudentInfo(models.Model):
# 新建3个字段,第一个字段是 主键id
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=20)
age = models.IntegerField()
# 默认会有个StudentInfo表,但是不好;所以务必通过Meta属性db_table来指定表名
class Meta:
db_table = 't_student'
# 先创建BookTypeInfo图书类型类,需要继承于models.Model
class BookTypeInfo(models.Model):
# 定义字段,首先定义id是自增主键
id = models.AutoField(primary_key=True)
# 再定义一个bookTypeName字段是CharField类型并指定最大长度20
bookTypeName = models.CharField(max_length=20)
# 定义Meta
class Meta:
# 指定表名
db_table = "t_bookType"
# 给模型取个直观的名字,主要是在Django5内置的admin系统里面给它娶个名字,以便管理
verbose_name = "图书类别信息"
# 如果verbose_name 后面没有_plural选项,则会在网站上类名后面自动拼接一个's'
verbose_name_plural = verbose_name
# 使用魔法方法__str__来重写一下打印"bookTypeName",默认打印对象输出图书类别名称
def __str__(self):
return self.bookTypeName
# 定义BookInfo类,依然是继承models.Model
class BookInfo(models.Model):
id = models.AutoField(primary_key=True)
# 图书名称
bookName = models.CharField(max_length=20, verbose_name='图书名称')
# 图书价格
price = models.FloatField(verbose_name='图书价格')
# 出版日期
publishDate = models.DateField(verbose_name='出版日期')
# 定义图书和图书类别的外键关联--bookType对象通过外键值取到图书类别的一个数据对象的封装
bookType = models.ForeignKey(BookTypeInfo, on_delete=models.PROTECT, verbose_name='图书类别')
class Meta:
db_table = "t_book"
verbose_name = "图书信息"
# 如果verbose_name 后面没有_plural选项,则会在网站上类名后面自动拼接一个's'
verbose_name_plural = "图书信息"
# 定义AccountInfo类,继承models.Model
class AccountInfo(models.Model):
# id字段可定义亦可不定义
id = models.AutoField(primary_key=True)
# 定义user用户
user = models.CharField(max_length=20)
# 定义某个用户的账户余额
account = models.FloatField()
class Meta:
# 数据库表名
db_table = "t_account"
# 给模型取个直观的名字
verbose_name = "用户账户信息"

24、使用普通管理员用户 test02 登录系统,打开修改图书信息页面,可以看到相关字段信息已显示为中文设置;

当然还有很多细粒度设置的方法,烦请自行查找官方文档学习了解;
- formfield_for_foreignkey()--设置外键下拉框过滤筛选;
- formfield_for_foreignkey()--重写外键下拉框数据,例如:增加下拉选项;
- save_model()--添加或者修改处理逻辑重写 ,可以增加一些日志等处理;
自定义 Admin 模版
Admin 后台管理系统的模版文件是 Django 框架内置提供的,可以在源码里找到;具体位置在"外部库 → <Python 3.XX > → Lib → site-packages → django → contrib → admin → templates " 下级菜单 admin 文件中;

在实际开发过程中,有很多时候需要修改默认的模版,包括程序功能,样式等,来达到业务需求;可以直接修改源码里的模版,但是这种方式不好,如果一台机器有多个项目,会影响其他项目使用;所以提倡在项目的模块项目的 templates 目录文件路径下,通过优先级来实现修改模版;在模块项目的"templates"目录文件路径下新建"admin"目录文件,然后在"admin"目录文件创建所需要覆盖的模版名称。
25、在"djangoProject"项目"helloWorld"应用"templates"目录文件路径下新建一个名称为"admin(名称固定,务必叫 admin)"的目录文件,在新建的 admin 目录文件路径下创建一个需要覆盖的模板名称(例如:change_form.html 修改图书信息模板),注意模板名称相同才能覆盖;以测试有效性的出发点来删除源码,自定义输入以下内容,刷新修改图书页面,可以看已经更改了,说明这种方式是有效的;
{% extends "admin/base_site.html" %}
{% load i18n admin_urls static admin_modify %}
{% block extrahead %}{{ block.super }}
<script src="{% url 'admin:jsi18n' %}"></script>
{{ media }}
{% endblock %}

烦请自行测试验证,最后注意测试过后记得还原或者可直接删除新创建的change_form.html 模板文件,这样就不会优先取模块项目应用路径下的模板文件了;以下 change_form.html 模板源码可供参考。
{% extends "admin/base_site.html" %}
{% load i18n admin_urls static admin_modify %}
{% block extrahead %}{{ block.super }}
<script src="{% url 'admin:jsi18n' %}"></script>
{{ media }}
{% endblock %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" href="{% static "admin/css/forms.css" %}">{% endblock %}
{% block coltype %}colM{% endblock %}
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-form{% endblock %}
{% if not is_popup %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% translate 'Home' %}</a>
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
› {% if has_view_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
› {% if add %}{% blocktranslate with name=opts.verbose_name %}Add {{ name }}{% endblocktranslate %}{% else %}{{ original|truncatewords:"18" }}{% endif %}
</div>
{% endblock %}
{% endif %}
{% block content %}<div id="content-main">
{% block object-tools %}
{% if change and not is_popup %}
<ul class="object-tools">
{% block object-tools-items %}
{% change_form_object_tools %}
{% endblock %}
</ul>
{% endif %}
{% endblock %}
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}{% if form_url %}action="{{ form_url }}" {% endif %}method="post" id="{{ opts.model_name }}_form" novalidate>{% csrf_token %}{% block form_top %}{% endblock %}
<div>
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1">{% endif %}
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}">{% endif %}
{% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}
{% if errors %}
<p class="errornote">
{% blocktranslate count counter=errors|length %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktranslate %}
</p>
{{ adminform.form.non_field_errors }}
{% endif %}
{% block field_sets %}
{% for fieldset in adminform %}
{% include "admin/includes/fieldset.html" %}
{% endfor %}
{% endblock %}
{% block after_field_sets %}{% endblock %}
{% block inline_field_sets %}
{% for inline_admin_formset in inline_admin_formsets %}
{% include inline_admin_formset.opts.template %}
{% endfor %}
{% endblock %}
{% block after_related_objects %}{% endblock %}
{% block submit_buttons_bottom %}{% submit_row %}{% endblock %}
{% block admin_change_form_document_ready %}
<script id="django-admin-form-add-constants"
src="{% static 'admin/js/change_form.js' %}"
{% if adminform and add %}
data-model-name="{{ opts.model_name }}"
{% endif %}
async>
</script>
{% endblock %}
{# JavaScript for prepopulated fields #}
{% prepopulated_fields_js %}
</div>
</form></div>
{% endblock %}
未完待续......