2024--Django平台开发-Django知识点(三)

  • day03 django知识点
    • 项目相关
    • 路由相关 urls.py
    • 视图相关 views.py
    • 模版相关 templates
    • 资源相关 static/media

1.项目相关

  • 新项目
    • 开发时,可能遇到使用其他的版本。
    • 虚拟环境
  • 老项目
    • 打开项目
    • 虚拟环境

1.1 关于新项目

1.系统解释器+命令行【学习】

C:/python38- python.exe- Scripts- pip.exe- pip3.8.exe- django-admin.exe- Lib- re.py- site-pakages- djangoC:/python39- python.exe- Scripts- pip.exe- pip3.9.exe- django-admin.exe- Lib- re.py- site-pakages- django
>>>C:/python39/Scripts/pip  install django
  • django项目

    >>>E:
    >>>cd code
    >>>C:/python39/Scripts/django-admin  startproject  mysite
    
  • 目录结构

    E:\code\mysite- mysite- urls.py     URL和函数对应关系- wsgi.py     底层请求处理入口【同步】- asgi.py     底层请求处理入口【异步】- settings.py 配置文件(内置配置文件global_settings假设200项配置 + 用户3项配置 =201配置)- manage.py       [管理项目]
    
  • 运行项目

    >>>cd mysite
    >>>C:\python39\python manage.py runserver 
    
  • 对应关系 urls.py

    from django.http import HttpResponsedef demo(request):return HttpResponse("OK")urlpattens = [path("demo/",demo),
    ]
    

2.虚拟环境+命令行【线上部署】

C:\python39- python.exe- Scripts- pip.exe- pip3.9.exe- virtualenv.exe- Lib- re.py- site-pakages
>>>C:\python39\pip install virtualenv
a.创建虚拟环境
>>>C:\python39\Scripts\virtualenv  F:\envs\x1  --python=python3.9
F:\envs\x1- python.exe- Scripts- pip.exe- pip3.9.exe- activate.exe- django-admin.exe- Lib- site-pakages- django- ..
b.激活虚拟环境
>>>F:
>>>cd F:\envs\x1\
>>>activate.exe
c.激活虚拟环境
(x1)>>>pip install django
(x1)>>>pip install django==3.2
d.创建项目
(x1)>>>django-admin startproject mysite

3.虚拟环境+Pycharm【最新django】

E:\PycharmProjects\day002
E:\PycharmProjects\day002\.venv

注意:第2期,都是基于这种方式去创建项目。

4.虚拟环境+Pycharm【老django】

本质:

  • 虚拟环境
  • 安装老版本django
  • 基于django-admin 创建项目
  • 在Pycharm中配置:项目 + 环境 => 绑定
a.虚拟环境

在这里插入图片描述

b.安装老版本django
(.venv) E:\PycharmProjects\day003>pip install django==3.2
c.创建django项目
(.venv) E:\PycharmProjects\day003>django-admin startproject day003
E:\PycharmProjects\day003\day003- day003...- manage.py
(.venv) E:\PycharmProjects\day003>django-admin startproject day003 .
E:\PycharmProjects\day003- day003...- manage.py
d.Pycharm配置

在这里插入图片描述

小结

  • 系统解释器 和 虚拟环境

  • 命令行【线上部署】

    • 安装virtualenv

    • 创建虚拟环境

    • 激活虚拟环境

    • 安装django

      pip install django
      pip install django==3.2
      
    • 创建新项目

      django-admin startproject xxxx
      
    • 编写代码

    • 运行项目

      python manage.py runserver 
      python manage.py runserver 8000
      python manage.py runserver 127.0.0.1:8000
      
  • Pycharm【开发】

    • 最新版本的django

      注意事项:pycharm为了防止大家用低版本pycharm,例如:2020.1版本的pycharm
      
    • 老旧版本的django

      • 虚拟环境

      • 安装老旧django

      • 创建项目

        django-admin startproject xxxx  .
        
      • Pycharm配置:项目 + 环境

1.2 关于老项目

  • 代码下载下来
  • 创建虚拟环境
  • 虚拟环境 + 项目绑定 + 安装必备的模块

注意:requirements.txt + Python解释器(问、文档)

1.3 纯净版项目

django内置有100个功能,5个功能是项目使用概率比较大。

  • 创建Django项目时,默认配置上功能。
  • 创建Django项目时,默认配置剔除。

Django纯净和Flask等轻量级框架的对比:

  • Flask,一个py文件项目,基于蓝图项目创建结构化。
  • Django,默认的配置,剔除 好几个文件。

a.创建项目

E:/PycharmProjects/day004- day004- urls.py     URL和函数对应关系- wsgi.py     底层请求处理入口【同步】- asgi.py     底层请求处理入口【异步】- settings.py 配置文件(内置配置文件global_settings假设200项配置 + 用户3项配置 =201配置)- manage.py       [管理项目]

b.默认功能

INSTALLED_APPS = ['django.contrib.admin',              # django内置后台管理,简单数据库的增删改查'django.contrib.auth',               # 用户登录和认证权限'django.contrib.contenttypes',       # 复杂表结构关系'django.contrib.sessions',           # 如果项目中有登录成功让用户可以访问。'django.contrib.messages',           # 消息展示,依赖Session'django.contrib.staticfiles',        # 静态资源处理,图片、css、js等
]
DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3','NAME': BASE_DIR / 'db.sqlite3',}
}
# 找功能模块,将功能模块中需要创建表结构,创建出来。
>>>python manage.py makemigrations          【找功能模块】【表结构】【生成配置文件并放到指定目录】
>>>python manage.py migrate                 【读取生成的配置文件,提交到数据库】
>>>python manage.py createsuperuser

纯净版配置:

# Application definitionINSTALLED_APPS = [# 'django.contrib.admin',# 'django.contrib.auth',# 'django.contrib.contenttypes',# 'django.contrib.sessions',# 'django.contrib.messages','django.contrib.staticfiles',
]MIDDLEWARE = ['django.middleware.security.SecurityMiddleware',# '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',
]TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [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',],},},
]
from django.contrib import admin
from django.urls import pathurlpatterns = [# path('admin/', admin.site.urls),
]

小结

  • 本地开发:基于Pycharm创建项目(新版本、老旧版)
  • 本地开发:打开别人的项目
  • 创建纯净版项目

1.4 关于APP

创建的django项目:

E:/PycharmProjects/day004- day004- urls.py     URL和函数对应关系- wsgi.py     底层请求处理入口【同步】- asgi.py     底层请求处理入口【异步】- settings.py 配置文件(内置配置文件global_settings假设200项配置 + 用户3项配置 =201配置)- manage.py       [管理项目]

关于APP,主要用于业务功能模块的开发。

  • 创建APP

    python manage.py startapp app01
    python manage.py startapp app02
    
    E:/PycharmProjects/day004- day004- urls.py     URL和视图函数对应关系- wsgi.py     底层请求处理入口【同步】- asgi.py     底层请求处理入口【异步】- settings.py 配置文件(内置配置文件global_settings假设200项配置 + 用户3项配置 =201配置)- manage.py       [管理项目]- app01- migrations  - ..- ...- models.py   用ORM代替原生SQL语句(对类和对象进行操作  -> SQL语句 -> 自动执行)编写类    +  makemigraions/migrate   -> 数据库- apps.py     "app01.apps.App01Config"- admin.py    配合django-admin可以对当前app中的表进行增删改查操作。- test.py     单元测试(不写单元测试)- views.py    业务功能【视图函数】- app02- migrations  - models.py- admin.py- apps.py- test.py- views.py
    

注意:一般情况下一个app就够了;开源组件;公共模块,拆分到单独的app模块。

多app应用的目录结构:

  • 单独1个app的项目 【推荐】

    E:/PycharmProjects/day004- day004- urls.py     URL和视图函数对应关系- wsgi.py     底层请求处理入口【同步】- asgi.py     底层请求处理入口【异步】- settings.py 配置文件(内置配置文件global_settings假设200项配置 + 用户3项配置 =201配置)- manage.py       [管理项目]- app01- migrations  - ..- ...- models.py   用ORM代替原生SQL语句(对类和对象进行操作  -> SQL语句 -> 自动执行)编写类    +  makemigraions/migrate   -> 数据库- apps.py     "app01.apps.App01Config"- admin.py    配合django-admin可以对当前app中的表进行增删改查操作。- test.py     单元测试(不写单元测试)- views.py    业务功能【视图函数】
    
  • 多个app

    在这里插入图片描述

  • 多个app,放在apps的文件夹中 【推荐】

    E:/PycharmProjects/day004- apps- app01- views.py- admins.py- models.py...- app02- views.py- admins.py- models.py...- app03- views.py- admins.py- models.py...- day004- urls.py     URL和视图函数对应关系- wsgi.py     底层请求处理入口【同步】- asgi.py     底层请求处理入口【异步】- settings.py 配置文件(内置配置文件global_settings假设200项配置 + 用户3项配置 =201配置)- manage.py       [管理项目]
    

    到底什么时候创建1个app?什么时候创建多个app?

    • 案例1:公司官网

      app01:  -> 公司官网开发,主要使用者:学员。
      app02:  -> 内部运营使用的功能模块
      app03:  -> 导师下载作业、批改作业、评分。
      
    • 案例2:公司官网【现阶段】

      app01:公司官网开发,主要使用者:学员。内部运营使用的功能模块导师下载作业、批改作业、评分。
      
      app01:  -> 公司官网开发,主要使用者:学员。
      app02:  -> 内部运营使用的功能模块
      app03:  -> 导师下载作业、批改作业、评分。
      

2.路由系统

2.1 常见操作

通俗的语言来表示:URL -> 函数对应关系

在这里插入图片描述

2.2 路由源码分析

2.2.1 路由定义的本质

在这里插入图片描述

from django.urls import path, re_path
from apps.www import viewsfrom django.urls import URLPattern
from django.urls.resolvers import RoutePatternurlpatterns = [URLPattern(RoutePattern("login/", name=None, is_endpoint=True), views.login, None, None),path('login/', views.login, name='n1'),# http://127.0.0.1:8000/info/2222/# http://127.0.0.1:8000/info/2222/?a1=1&b1=2# path('info/<int:v1>/', views.info),# http://127.0.0.1:8000/other/11/yiyebaitou/# http://127.0.0.1:8000/other/222/shiyi/# path('other/<int:v1>/<str:v2>/', views.other),# path('xx/<path:v2>/', views.xx),# path('xx/<uuid:v2>/', views.xx),# http://127.0.0.1:8000/yy/2014-11-11# re_path(r'yy/(\d{4})-(\d{2})-(\d{2})/', views.yy),
]
  • 编写路由

  • 启动项目时

    urlpatterns = [对象(URL地址、函数),对象(URL地址、函数),对象,对象,对象,URLPattern(RoutePattern("login/", name=None, is_endpoint=True), views.login, None, None),
    ]# 内部路由匹配的时,默认执行:
    URLPattern.resolveself.pattern.match()return ResolverMatch(...)# 进阶操作
    # 路由系统中的扩展点:URLPattern.resolveRoutePattern.match自定义ResolverMatch类
    
  • 用户浏览器访问

    http://127.0.0.1:8000/login/
    
  • django的源码内部,一定会匹配,获得相应的视图函数

    http://127.0.0.1:8000 /login/urlpatterns = [对象(URL地址、函数),对象(URL地址、函数),对象,对象,对象
    ]
    
    urlconf = 'day006.urls'
    resolver = URLResolver(RegexPattern(r"^/"), urlconf)resolver_match = resolver.resolve(request.path_info)callback, callback_args, callback_kwargs = resolver_match
    
  • 执行视图函数

听完的感受:

  • 流程是懵逼,Django请求的流程懵逼【证明】。

  • 我们需要基于源码记住

    urlpatterns = [path('login/', views.login),path('info/<int:v1>/', views.info),
    ]
    
    urlpatterns = [URLPattern(RoutePattern("login/", name=None, is_endpoint=True), views.login, None, None),URLPattern(RoutePattern("login/", name=None, is_endpoint=True), views.login, None, None),URLPattern(RoutePattern("login/", name=None, is_endpoint=True), views.login, None, None),URLPattern(RoutePattern("login/", name=None, is_endpoint=True), views.login, None, None),
    ]
    
  • 源码内部路由匹配的时,是怎么做的?

    URLPattern.resolveRoutePattern.match
    
    def resolve(self, path):match = self.pattern.match(path)if match:new_path, args, captured_kwargs = match# Pass any default args as **kwargs.kwargs = {**captured_kwargs, **self.default_args}return ResolverMatch(self.callback,args,kwargs,self.pattern.name,route=str(self.pattern),captured_kwargs=captured_kwargs,extra_kwargs=self.default_args,)
        def match(self, path):match = self.regex.search(path)if match:# RoutePattern doesn't allow non-named groups so args are ignored.kwargs = match.groupdict()for key, value in kwargs.items():converter = self.converters[key]try:kwargs[key] = converter.to_python(value)except ValueError:return Nonereturn path[match.end() :], (), kwargsreturn None

2.3 name别名

path('login/', views.login, name='n1'),
URLPattern(RoutePattern("login/", name="n1", is_endpoint=True), views.login, None, "n1"),
def login(request):return HttpResponse("欢迎登陆")
from django.urls import reverseresult = reverse("n1")
print(result) # "login/"
path('api/auth/login/<int:v1>/', views.login, name='n1'),
def login(request,v1):return HttpResponse("欢迎登陆")
from django.urls import reverseresult = reverse("n1",kwargs={"v1":123})
print(result) # "/api/auth/login/123/"result = reverse("n1",kwargs={"v1":999})
print(result) # "/api/auth/login/999/"

name存在的意义?例如:用户登录登录程序

/api/auth/login/         ->   函数登录
/api/user/account/      ->    函数账单
path('api/auth/login/',  views.login,  name='n1'),
path('api/user/account/', views.account, name='n2'),
def login(request):# 当用户登录成功之后,需要让用户跳转到 /api/user/account/ 页面# return redirect("/api/user/account/")# url = reverse("n2")   # "/api/user/account/"# return redirect(url)return redirect("n2")def account(request):return HttpResponse("用户信息")

name存在的意义?例如:权限管理

A用户有权访问的网址:/api/auth/login/ /api/user/account//api/user/order//api/user/order/<int:v1>/B用户有权访问的网址:/api/user/account//api/user/order//api/user/order/<int:v1>/
A用户有权访问的网址:n1n2n3B用户有权访问的网址:n2n3

总结

  1. 创建Django项目

    • 虚拟环境 + 新版本
    • 虚拟环境 + 老旧版
  2. app的概念

    • 1个app
    • 多个app(apps文件夹)
  3. 路由系统

    • 【必备】常见路由操作

      # http://127.0.0.1:8000/info/2222/
      # http://127.0.0.1:8000/info/2222/?a1=1&b1=2
      path('info/<int:v1>/', views.info),# http://127.0.0.1:8000/other/11/yiyebaitou/
      # http://127.0.0.1:8000/other/222/shiyi/
      path('other/<int:v1>/<str:v2>/', views.other),# path('xx/<path:v2>/', views.xx),
      # path('xx/<uuid:v2>/', views.xx),# http://127.0.0.1:8000/yy/2014-11-11
      re_path(r'yy/(\d{4})-(\d{2})-(\d{2})/', views.yy),
      

      在这里插入图片描述

    • 【必备】name别名

      • 反向别名生成URL地址
      • 权限分配,不会用URL网址而是使用name别名。
    • 【可选】源码的流程+扩展点

      MyURLPattern(MyRoutePattern("login/", name=None, is_endpoint=True), views.login, None, None),
      URLPattern(RoutePattern("login/", name="n1", is_endpoint=True), views.login, None, "n1"),
      
      django.urls.resolvers.URLResolver.resolve
      django.urls.URLPattern.resolve
      django.urls.resolvers.RoutePattern.match
      
      django.urls.resolvers.URLResolver.resolvefor obj in ....:# django.urls.URLPattern.resolve# obj.resolve# self.pattern.matchdjango.urls.resolvers.RoutePattern.match
      

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/611732.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

BUUCTF ---> Encrypto

转眼就一月十号了&#xff0c;本来今天不想更的&#xff0c;&#xff08;因为我懒&#xff09;是因为明天要考python&#xff0c;好像还不止 但是呢&#xff0c;发现BUUCTF的密码学模块刚好可以用到py的脚本&#xff0c;那就当时复习一下吧&#xff01;&#xff01; 这里就要介…

您的计算机已被.LIVE勒索病毒感染?恢复您的数据的方法在这里!

引言&#xff1a; 在数字时代&#xff0c;.LIVE勒索病毒如暗夜中的黑暗调&#xff0c;威胁着个人和企业的数字安全。本文将深入介绍.LIVE勒索病毒的特征&#xff0c;提供解密数据的方法&#xff0c;并讨论预防措施&#xff0c;让我们共同筑起数字世界的防护之墙。数据的重要性…

C++学习笔记——返回对象

一、返回对象 当我们说一个函数返回对象时&#xff0c;意味着该函数的返回值是一个对象。这种情况下&#xff0c;函数可以通过创建对象的副本、返回对象的引用或者返回对象的指针来实现。 返回对象的副本&#xff1a; 当一个函数返回对象的副本时&#xff0c;函数内部会创建一…

Mac上修复Gitee报错 Oauth: Access token is expired

一. 背景&#xff1a; 最近在gitee上拉了两次项目&#xff0c;两次使用的邮箱密码不一致&#xff08;换绑邮箱&#xff09;&#xff0c;第一次在idea中拉取后端项目&#xff0c;第二次在webstorm中拉取前端项目&#xff0c;出现该异常&#xff0c;记录下解决方案 二. 错误回显…

简易机器学习笔记(九)LeNet实例 - 在眼疾识别数据集iChallenge-PM上的应用

前言 上一节大概讲了一下LeNet的内容&#xff0c;这一章就直接来用&#xff0c;实际上用一下LeNet来进行训练和分类试试。 调用的数据集&#xff1a; https://aistudio.baidu.com/datasetdetail/19065 说明&#xff1a; 如今近视已经成为困扰人们健康的一项全球性负担&…

整形数据在内存中的存储(C语言)

整形数据在内存中的存储 1.整形家族2.(原码、反码、补码)基础知识3.大小端3.1 什么是大小端3.2 为什么有大端和小端3.3 一道关于大小端字节序的面试题3.4 关于整形数据存储的题目(7题)3.4.13.4.23.4.33.4.43.4.53.4.63.4.7 4.总结 1.整形家族 signed可省可不省&#xff0c;一般…

Spring创建的单例对象,存在线程安全问题吗?

这个问题涉及到Spring框架中的Bean的作用域、单例模式的线程安全性以及如何判断和处理线程安全问题。让我们一步步深入探讨这些概念。 Spring Bean的作用域 Spring提供了几种不同的Bean作用域&#xff0c;包括&#xff1a; 1、 Singleton&#xff08;单例&#xff09;&#x…

​​​​​​​Lontium #LT8911EXB适用于MIPIDSI/CSI转EDP应用方案,分辨率高达2560x1440@60HZ 。

1.描述 LT8911EXB是一款高性能 MIPIDSI/CSI到eDP转换器&#xff0c;单端口MIPI接收器有1个时钟通道和4个数据通道&#xff0c;每个数据通道最大运行2.0Gbps&#xff0c;最大输入带宽为8.0Gbps。转换器解码输入MIPI RGB16/18/24/30/36bpp、YUV422 16/20/24bpp、YUV420 12bpp包&…

Kubernetes实战(十五)-Pod垂直自动伸缩VPA实战

1 介绍 VPA 全称 Vertical Pod Autoscaler&#xff0c;即垂直 Pod 自动扩缩容&#xff0c;它根据容器资源使用率自动设置 CPU 和 内存 的requests&#xff0c;从而允许在节点上进行适当的调度&#xff0c;以便为每个 Pod 提供适当的资源。 它既可以缩小过度请求资源的容器&…

C# HttpClient Get Post简单封装

文章目录 前言封装好的代码测试接口测试代码 前言 微软官方有Get和Post请求&#xff0c;我把他简单化处理一下 封装好的代码 public class MyHttpHelper{private string baseUrl;/// <summary>/// 基础Api/// </summary>public string BaseUrl{get{return baseUr…

还不会python 实现常用的数据编码和对称加密?看这篇文章就够啦~

相信很多使用 python 的小伙伴在工作中都遇到过&#xff0c;对数据进行相关编码或加密的需求&#xff0c;今天这篇文章主要给大家介绍对于一些常用的数据编码和数据加密的方式&#xff0c;如何使用 python 去实现。话不多说&#xff0c;接下来直接进入主题&#xff1a; 前言 1…

EasyPOI导出报表

报表导出是一种很常见的功能&#xff0c;只要是开发都会涉及到这一功能&#xff0c;早些年经常集成poi完成导出功能&#xff0c;我之前也有写过关于poi导出的文章&#xff0c;现如今&#xff0c;也有了更为方便的导出插件 — EasyPOI&#xff0c;废话不多说&#xff0c;开始撸代…

【刷题篇】动态规划(八)

文章目录 1、分割回文串 IV2、分割回文串 II3、最长回文子序列4、让字符串成为回文串的最少插入次数5、最长公共子序列6、不相交的线 1、分割回文串 IV 给你一个字符串 s &#xff0c;如果可以将它分割成三个 非空 回文子字符串&#xff0c;那么返回 true &#xff0c;否则返回…

浅述热点方向-具身智能

具身智能 1. 具身智能&#xff08;Embodied AI&#xff09;概述 人工智能、机器学习和计算机视觉的最新研究趋势催生了一个不断增长的研究领域&#xff0c;称为“具身智能”。Facebook 人工智能研究中心 (FAIR) 和英特尔实验室一直在引领嵌入式人工智能领域的新项目。“体现”…

2024阿里云服务器ECS实例全方位介绍_优缺点大全

阿里云服务器ECS英文全程Elastic Compute Service&#xff0c;云服务器ECS是一种安全可靠、弹性可伸缩的云计算服务&#xff0c;阿里云提供多种云服务器ECS实例规格&#xff0c;如经济型e实例、通用算力型u1、ECS计算型c7、通用型g7、GPU实例等&#xff0c;阿里云服务器网aliyu…

安卓多用户管理之adb指令

前言 有一些与多用户相关的adb 指令可以更好地帮助我们了解和调试安卓多用户相关信息 一、多用户adb指令 查看用户列表   adb shell pm list users 查看用户信息&#xff1a; adb shell dumpsys user 创建新用户   adb shell pm create-user [–profileOf userId] [–mana…

常用服务器管理面板整理汇总

服务器管理面板是用于管理和控制服务器的软件&#xff0c;可以帮助管理员更轻松地进行服务器管理和维护。以下是几种常用的服务器管理面板&#xff1a; 1、宝塔面板【官网直达】 宝塔面板是一款服务器运维管理软件&#xff0c;支持Windows和Linux等操作系统&#xff0c;提供了…

three.js实现渐变墙效果(电子围栏)

three.js实现渐变墙效果&#xff08;电子围栏&#xff09; 图例 步骤 两个平面几何体&#xff0c;添加纹理贴图平移纹理贴图 代码 <template><div class"app"><div ref"canvesRef" class"canvas-wrap"></div></d…

【uniapp】遇到的一些问题

一、小程序中textarea ios样式不生效的方法 默认有内边距&#xff0c;加个disable-default-padding"true" 二、uni-data-picker循环使用&#xff0c;一个改了全局的值 换成了uni自带的picker&#xff0c;下面括号里必须有默认值&#xff0c;为空字符串的时候&…

软件架构之事件驱动架构

一、定义 事件驱动的架构是围绕事件的发布、捕获、处理和存储&#xff08;或持久化&#xff09;而构建的集成模型。 某个应用或服务执行一项操作或经历另一个应用或服务可能想知道的更改时&#xff0c;就会发布一个事件&#xff08;也就是对该操作或更改的记录&#xff09;&am…