Django 基础知识详细图文教程 15-Django 内置Admin系统

来源引用网络知识与某站曹老师视频相互结合学习记录,仅供参考!

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;

  1. class BookInfoAdmin(admin.ModelAdmin)--自定义类BookInfoAdmin,需要继承 ModelAdmin 父类;
  2. @admin.register(BookInfo)--需要在自定义类上加@admin.register(),里面添加需要注册哪个;
  3. 自定义类里面可以写一些精细化配置信息(包括每页大小、过滤条件、显示字段、查询字段、排序等等),具体可查看参考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>
&rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
&rsaquo; {% if has_view_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
&rsaquo; {% 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 %}

未完待续......

相关推荐
夜晚回家1 小时前
Python 变量入门详解 | 用 BMI 案例串起赋值、乘方与取整
android·python
技术人生0011 小时前
Selenium4 Python 完整教程(适合网页自动化、页面数据采集、UI自动化测试)
python·ui·自动化
柠檬味拥抱1 小时前
皮肤病变检测数据集 | 2500张YOLO皮肤科数据集
后端
小小张说故事1 小时前
Python 里 a is b 有时 True 有时 False?小整数缓存和常量折叠的底层真相
python
我的xiaodoujiao1 小时前
Django 基础知识详细图文教程 16-Django 内置Admin认证系统
后端·python·django
ZGonce8191 小时前
vLLM 使用实战:在 8GB 显卡上完成模型部署、并发压测与显存调优
python
程序员鱼皮1 小时前
Personal Agent 是什么?为什么大厂都抢着做?连 DeepSeek Bot 都来了。。
前端·后端·ai编程
geovindu1 小时前
rust: Chain of Responsibility Pattern
开发语言·后端·设计模式·rust·责任链模式·行为模式
m0_587383001 小时前
碰碰好评卡功能落地全流程实战指南 附核心逻辑与常见问题解决方案
java·前端·数据库·后端·struts·需求分析