Web框架(web framework)或者叫作Web应用框架(web application framework),是用于进行web开发的一套软件结构。大多数的web框架提供了一套开发和部署网站的方式,为web行为提供了一套支持方法。使用web框架,不少业务逻辑外的功能不须要本身再去完善,而是使用框架已有的功能就能够了。html
Web框架可分为MVC(Model模型、Views视图、Controller控制器)和MTV(Model模型、Templates模板、Views视图)。前端
Django是一个流行的开源的基于Python的重量级Web框架,集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能。Django使用了MTV模式。python
Django的设计十分优美:web
Django官网https://www.djangoproject.com/。ajax
使用pip install django便可安装Django。当前使用pip安装的Django版本为2.0.3。正则表达式
安装Django后,便可使用如下命令建立Django工程:redis
django-admin startproject 工程名称
Django工程建立完成后,在指定目录将出现如下结构的目录:数据库
工程名称/ | | -- 工程名称/ | | -- init.py | | -- settings.py # Django的配置文件 | | -- urls.py # Django路由系统 | | -- wsgi.py # Django遵循WSGI规范 | | -- manage.py # Django的管理功能 | | -- templates/ # 使用IDE建立工程时会自动建立,用于存放模板文件(即HTML)
启动该Django工程:django
# 在工程目录下运行 python manage.py runserver host:port
建立APP的目的在于将业务逻辑分开,每一个具体的APP实现一个具体的业务。浏览器
使用如下命令建立APP:
python manage.py startapp app名称
建立完APP后,将出现如下结构的目录:
# 从APP目录开始 APP名称/ | | -- migrations/ # 建立或修改数据库表结构时会在该文件夹下建立记录 | | -- admin.py # Django提供的后台管理功能 | | -- apps.py # 用于配置当前的APP | | -- models.py # Django提供的ORM,经过类便可建立数据库结构 | | -- tests.py # 单元测试 | | -- views.py # 视图文件,编写业务代码
配置模板路径:
# 在settings.py中的TEMPLATES = 下修改 'DIRS': [os.path.join(BASE_DIR, "templates")],
配置静态文件路径:
# 静态文件目录可命名为static # 在settings.py文件中的STATIC_URL = '/static/'下添加 STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'), )
链接Django请求的整个生命周期,咱们就能够根据该周期来使用Django。
当用户的请求到来时,首先到达的是Django的路由系统,Django根据路由系统里面的配置把请求转给相应的视图函数,视图函数根据请求的具体内容从模板或数据库中提取数据以后通过渲染后返回给用户。整个生命周期以下:
用户请求 ---> 中间件 ---> 路由系统 ---> 视图函数 ---> 模板渲染 ---> 展现给用户最终结果
在Django中,中间件其实就是一个类,在请求到来和结束以后,Django会根据本身的规则在合适的时机执行中间件中相应的方法。
中间件在settings.py中的MIDDLEWARE = []中配置,里面的每个项即为一个中间件。
自定义中间件:
# 在xx目录下建立xxx.py文件 from django.utils.deprecation import MiddlewareMixin class F1(MiddlewareMixin): # 中间件中能够定义如下五种方法 def process_request(self, request): # 请求来时首先经过该方法 pass # 不能return,不然没法到达Views函数 def process_view(self, request, callback, callback_args, callback_kwargs): # 全部中间件的request方法执行完成,URL匹配成功并获取Views函数的名称和参数后执行该方法(Views函数不执行) pass def process_template_response(self, request, response): # 只有在Views函数的返回值中有render方法时执行 pass def process_exception(self, request, exception): # 只有在Views函数出错时执行 pass def process_response(self, response): # 中间件其余方法或Views函数执行完成后执行 pass return response # 必须return response,不然前一个中间件没法获取到返回值 # 以上方法的返回值能够是None和HttpResponse对象。若是是None,则继续按照Django定义的规则向下执行,若是是HttpResponse对象,则直接将该对象返回给用户 # 在settings.py中注册中间件 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', 'xx.xxx' # 根据中间件须要在合适执行决定放置位置 ]
中间件的整个执行过程:
Django的路由系统就是URL与视图函数的对应关系,在urls.py文件中配置。Django支持一个URL对应一个视图函数、一组URL(使用正则表达式)对应一个视图函数。
一个URL对应一个视图函数:
# 在urls.py文件中添加 urlpatterns = [ path('admin/', admin.site.urls), # Django自带的后台管理 path('URL', 视图函数), ]
一组URL对应一个视图函数:
# 在urls.py文件中添加 urlpatterns = [ re_path('URL带正则表达式', 视图函数), ] e.g: urlpatterns = [ re_path('home-(\d+)', 视图函数), ] # 使用多少个正则表达式,就会向视图函数传递相应数量的参数,视图函数必须接收这些参数,能够设置*args和**kwargs # 推荐使用正则表达式分组 e.g: urlpatterns = [ re_path('home-(?<Pnid>\d+)', 视图函数), ]
添加默认值:
# 在URL中添加默认值 urlpatterns = [ path('URL', 视图函数, {"xx": "xxx"}), ] # 在视图函数中必须接收该默认值 def func(request, xx): print(xx)
路由分发:
# 当APP增多时,不一样的APP可能使用到相同的URL,这时若是都在urls.py中添加的话将照成冲突,咱们就可使用到Django的路由分发功能 # 在urls.py中添加 from django.urls import include urlpatterns = [ path('一类URL', include("APP名称.urls")), ] # 这时在对应APP目录下建立urls.py文件编写路由便可 e.g: from django.urls import include urlpatterns = [ path('cmdb/', include("cmdb.urls")), ] # 此时在浏览器访问host:port/cmdb/URL
path和re_path可加name参数,为该URL设置一个名称:
urlpatterns = [ path('URL', 视图函数, name='自定义名称'), re_path('URL', 视图函数, name='自定义名称'), ] # 在HTML中可使用模板语言来调用该名称 {% url "自定义名称" 参数(随便填,xxx=若是有正则) %}
命名空间:
name参数没有做用域,Django在反解URL时,会在项目全局顺序搜索,当查找到第一个name指定的URL时,当即返回,当不当心定义相同的name时,可能会致使URL反解错误,为了不该错误发生,可以使用命名空间
# 在urls.py中添加 from django.urls import include urlpatterns = [ path('一类URL', include("APP名称.urls"), namespace= "aaa"), ] # 在对应APP目录下建立的urls.py文件添加 from django.urls import path from xxx import views app_name = "xxx" urlpatterns = [ path('bbb/', views.xxx, name="index"), ] # 这时,使用反解获得的URL print(reverse("xxx:index")) # /aaabbb/
在Django中自动生成URL:
from django.urls import reverse reverse('URL', args=(n,...)) reverse('URL', kwargs={}) # 使用此方法生成的URL将带有后面第二个参数的内容
FBV即function、base、view,是URL与函数的对应,CBV即class、base、view,是URL与类的对应。
FBV路由编写:
urlpatterns = [ path('URL', 函数), ]
CBV路由编写:
urlpatterns = [ path('URL', 类.as_view()), ]
FBV函数编写:
def func(request): pass # request为客户端传入的全部请求
CBV中的类编写:
from django.views import View class Foo(View): def get(self, request): # 传入GET请求 pass def post(self, request): # 传入POST请求 pass
FBV与CBV使用装饰器:
# FBV使用装饰器与平时同样 # 装饰器xxx @xxx def func(request): pass # CBV使用装饰器时,需进行以下操做 from django.utils.decorators import method_decorator # 单个方法使用装饰器 class Obj(views.View): @method_decorator(xxx) def get(self, request): pass def post(self, request): pass @method_decorator(xxx, name="使用装饰器的方法") class Obj(views.View): def get(self, request): pass def post(self, request): pass # 整个类使用装饰器 @method_decorator(xxx, name="dispatch") class Obj(views.View): def get(self, request): pass def post(self, request): pass
视图函数用于处理用户发送到服务端的请求,处理相应的业务,在相应APP目录下的views.py文件中编写。
def func(request): request.method # 用于判断客户端传入的请求类型,如GET、POST,值均为大写 request.GET/POST # 接收客户端相应请求类型下的数据,字典模式 request.POST.get() # 由于请求中的数据为字典类型,因此可使用get取相应key的value,这里不推荐使用[],由于使用[]时若相应的key不存在则会报错 request.POST.getlist() # 用于获取返回值是多个数据,如checkbox的返回值 obj = request.FILES.get() # 上传文件时,生成一个实例 obj.name # 获取文件名 obj.size # 获取文件的字节数 obj.chunks # 获取文件的数据块,当文件上传时分为一个个数据块上传,能够循环该方法接收完整的文件数据,也能够直接循环obj,Django内部将调用chunks request.path_info # 获取当前URL # request在前端也能够拿到,能够经过模板语言使用
获取用户请求头及请求主体信息:
# 用户传入的请求包含请求头和请求主体信息,使用如下方法获取所有信息 from django.core.handlers.wsgi import WSGIRequest
request.environ # 将以字典形式返回全部的信息 # 直接获取未通过Django处理的原生请求数据 # 获取请求头 request.Meta # 获取请求主体 request.body # 如下方法属于请求头信息 request.method request.path_info request.COOKIES # 如下方法属于请求主体信息 request.GET requets.POST request.FILES
Django的模板语言用于接收后台返回的数据并将数据嵌入HTML中。
{{ xxx }} # 用后台返回的内容替换HTML e.g: <span>{{ xxx }}</span>
模板语言中取列表和字典的值:
# 取列表值 list = [] list.下标 # 取字典的值 dict = {} dict.key
for循环:
{% for item in xxx %} ...... {% endfor %} # for循环中有如下几个方法 # forloop.counter,计数器 # forloop.revcounter,倒数计数器 # forloop.counter0,从0开始的计数器 # forloop.revcounter0,从0开始的倒数计数器 # forloop.first,是否第一个循环 # forloop.last,是否最后一个循环 # forloop.parentloop,父循环的以上6个信息
if语句:
{% if xxx %} ...... {% else %} ...... {% endif %}
使用模板语言循环字典:
# 循环字典的键 {% for item in dict.keys %} {% endfor %} # 循环字典的值 {% for item in dict.values %} {% endfor %} # 循环字典的键值对 {% for k, v in dict.items %} {% endfor %}
模板的继承:
# 建立模板HTML,通用部分写HTML,改变的部分以下: {% block 名称 %} {% endblock %} # 须要使用模板的其余HTML文件 {% extends "模板HTML" %} # 声明继承的模板 {% block 模板中的block名称 %} HTML代码... {% endblock %} # 注意,只能继承一个模板
导入模板组件:
能够将HTML页面中常用的部分设计成小组件,在其余页面须要使用的时候导入便可。
# 建立一个HTML文件,写HTML代码 # 须要引入时使用: {% include "HTML文件" %}
自定义simple_tag:
自定义simple_tag容许用户在模板语言中使用本身定义的Python函数,具体步骤以下,
1.在APP中建立templatetags目录(Python Package)
2.在目录中建立任意py文件
# 建立xxx.py文件 from django import template register = template.Library() @register.simple_tag def func(x1, x2, …): ...
3.在使用自定义simple_tag的HTML文件中导入以前建立的xxx.py
{% load xxx %}
4.使用自定义simple_tag
{% func 参数1 参数2 …%}
注意:使用自定义simple_tag以前必须在settings.py中的INSTALLED_APPS中注册该APP。
自定义filter:
自定义filter相似自定义simple_tag,具体步骤以下,
1.在APP中建立templatetags目录(Python Package)
2.在目录中建立任意py文件
# 建立xxx.py文件 from django import template register = template.Library() @register.filter def func(x1, x2): ...
3.在使用自定义filter的HTML文件中导入以前建立的xxx.py
{% load xxx %}
4.使用自定义filter
{{ 参数1|func:参数2 }} # 注意:函数的参数跟函数间不能有空格
自定义simple_tag与自定义filter的区别:
自定义simple_tag能够传入多个参数,可是不能做为if语句的条件;自定义filter只能传入两个参数,可是能够做为if语句的条件使用
Django有如下三种方式能够给用户返回最终结果
# 返回字符串 from django.shortcuts import HttpResponse return HttpResponse("字符串" or "字节") # 返回模板文件(HTML) from django.shortcuts import render return render(request, "模板文件路径", {字典,返回内容给模板语言}) # 返回一个URL from django.shortcuts import redirect return redirect("URL")
Cookie是在HTTP协议下,服务器或脚本能够维护客户工做站上信息的一种方式。Cookie是由WEB服务器保存在用户浏览器上的一个小文件,经过相似字典的键值对方式存储有关用户的信息,不管什么时候用户链接到服务器,WEB站点均可以访问Cookie中的信息。
获取Cookie:
def func(request): request.COOKIES["xxx"] request.COOKIES.get("xxx")
设置Cookie:
def func(request): rep = HttpResponse or rep = render(request, xx.html) rep.set_cookie(key, value, ...) # 参数: # key --> 键 # value --> 值 # max_age= --> 超时时间,秒 # expires= --> 超时时间,具体日期 # path="/" --> Cookie生效的路劲,/表示根路径,根路径的Cookie能够被任何页面访问 # domain= --> Cookie生效的域名 # secure=True/False --> HTTPS传输 # httponly=True/False --> 只能HTTP协议传输,没法被JS获取
注意:不设置Cookie超时时间时,Cookie在关闭浏览器前均有效。
将Cookie失效时间设置为当前时间便可清除Cookie。
加密Cookie:
# 获取加密Cookie def func(request): request.get_signed_cookie(key, default=RAISE_ERROR,salt="加密盐", max_age=) # 设置加密Cookie def func(request): rep = HttpResponse() or rep = render(request, xx.html) rep.set_signed_cookie(key, value, salt="加密盐", ...)
注意:因为Cookie存储与客户端,因此在基于Cookie的用户认证中,为了安全不建议将敏感信息放置于Cookie中。
Session,在计算机中,尤为是在网络应用中,被称为“会话控制”。Session对象存储特定用户会话过程当中所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,若是该用户尚未会话,则 Web 服务器将自动建立一个 Session 对象。当会话过时或被放弃后,服务器将终止该会话。
与Cookie相同的是,Session也是经过键值对的形式保存信息;而与Cookie不一样的是,Session保存在服务器端而非客户端。可是Session必须与Cookie配合使用,Session会将该项生成的一段随机字符串保存在Cookie中,其余信息则保存在服务端。
在Django中,默认状况下Session保存在Django自带的数据库中,因此在使用Session前必须先进行建立数据库的操做。
Django中Session的使用:
def func(request): # 获取Session request.session["xxx"] request.session.get("xxx") # 设置Session request.session["xxx"] = xxx request.session.setdefault("xxx", xxx) # 不存在则设置 # 删除Session del request.session["xxx"] # 全部键、值、键值对操做 request.session.keys() request.session.values() request.session.items() request.session.iterkeys() request.session.itervalues() request.session.iteritems() # Session随机字符串 request.session.session_key() # 删除全部失效日期小于当前日期的Session request.session.clear_expired() # 检查用户Session随机字符串在数据库中是否存在 request.session.exists("session_key") # 删除当前用户全部的Session request.session.clear() request.session.delete("session_key") # 设置Session失效时间 request.session.set_expiry(value) # 参数: # value为整数 --> Session会在设置的秒数后失效 # value为datatime或timedelta --> Session会在这个时间后失效 # value为0 --> Session会在关闭浏览器时失效 # value为None --> Session依赖settings.py中设置的失效策略,默认为两周
settings.py中可配置Session默认行为:
# 引擎(默认) SESSION_ENGINE = 'django.contrib.sessions.backends.db' # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认) SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存的路径(默认) SESSION_COOKIE_PATH = "/" # Session的cookie保存的域名(默认) SESSION_COOKIE_DOMAIN = None # 是否Https传输cookie(默认) SESSION_COOKIE_SECURE = False # 是否Session的cookie只支持http传输(默认) # Session的cookie失效日期(2周)(默认) SESSION_COOKIE_AGE = 1209600 # 是否关闭浏览器使得Session过时(默认) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否每次请求都保存Session,默认修改以后才保存(默认) SESSION_SAVE_EVERY_REQUEST = False
Django中默认将Session保存在自带数据库的django_session表中,也能够将Session保存在其余地方,Django提供了如下5种类型供开发者使用:
经过配置settings.py中的SESSION_ENGINE = “”便可修改保存方式
# 数据库 SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 缓存 SESSION_ENGINE = 'django.contrib.sessions.backends.cache' SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也能够是memcache),此处别名依赖缓存的设置 # 文件 SESSION_ENGINE = 'django.contrib.sessions.backends.file' SESSION_FILE_PATH = None # 缓存文件路径,若是为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() # 缓存+数据库,数据库用于作持久化,缓存用于提升效率 SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 加密Cookie SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
XSS全称跨站脚本攻击,是一种在WEB应用中的计算机安全漏洞,它容许恶意WEB用户将代码(如HTML代码和JS脚本)植入到提供给其余用户使用的页面中。
为了防止XSS攻击,Django后台在返回给前台的数据中出现如HTML代码或JS脚本的字符串时,在前台将按字符串显示,而不会将代码解析未HTML或脚本。当咱们须要将返回的代码或脚本实现功能而不已字符串显示时,可使用以下方法:
# 后台Views函数 from django.shortcuts import HttpResponse from django.utils.safestring import mark_safe def func(request): xxx = "<a href='www.baidu.com'>百度一下</a>" xxx = mark_safe(xxx) return HttpResponse(xxx) # 前台HTML文件,使用模板语言 {{ xxx|safe }}
CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者“Session Riding”,是一种对网站的恶意利用。尽管听起来像跨站脚本XSS,但它与XSS很是不一样,XSS利用站点内的信任用户,而CSRF则经过假装来自受信任用户的请求来利用受信任的网站。
Django中的中间件django.middleware.csrf.CsrfViewMiddleware提供了全局防止CSRF攻击的功能,在Views函数中也能够设置局部防止CSRF攻击的功能。
全局防止CSRF:
启用中间件django.middleware.csrf.CsrfViewMiddleware
局部防止CSRF:
from django.views.decorators.csrf import csrf_exempt, csrf_protect # 当前函数设置防止CSRF攻击,即便中间件没有启用 @csrf_protect def func(request): ... # 当前函数取消防止CSRF攻击,即便中间件启用 @csrf_exempt def func(request): ...
前台设置csrf token
form表单:
<form> {% csrf_token %} </form>
Ajax:
csrf token也保存在cookie中,因此在Ajax提交数据时可使用保存在cookie中的csrf token
1.单个Ajax设置
$.ajax({ headers:{"X-CSRFtoken": $.cookie('csrftoken')}, })
2.全局Ajax设置
$.ajaxSetup({ beforeSend: function(xhr, settings){ xhr.setRequestHeader("X-CSRFtoken", $.cookie("csrftoken")); } });
若是每次请求时都去数据库中进行相应的操做,在访问量大时,耗时必然会更加明显。对于这种情况最简单的解决方法既是使用缓存,将某个Views的返回值保存在内存或者缓存服务器中,当必定的时间内有用户访问时,直接从内存或缓存中读取数据返回给用户。
Django中提供了如下6种方式使用缓存:
缓存的配置也在settings.py中进行:
# 开发模式 CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 引擎 'TIMEOUT': 300, # 缓存超时时间(默认300,None表示永不过时,0表示当即过时) 'OPTIONS':{ 'MAX_ENTRIES': 300, # 最大缓存个数(默认300) 'CULL_FREQUENCY': 3, # 缓存到达最大个数以后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3) }, 'KEY_PREFIX': ' ', # 缓存key的前缀(默认空) 'VERSION': 1, # 缓存key的版本(默认1) 'KEY_FUNCTION': 函数名, # 生成key的函数(默认函数会生成为:【前缀:版本:key】) } } # 内存,将内容保存在内存的变量中 CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', 'LOCATION': 'unique-snowflake', ... } } # 文件,将内容保存在文件中 CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': '文件路径', ... } } #数据库,将内容保存在数据库中 CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.db.DatabaseCache', 'LOCATION': '表名', } } # Memcache(python-memcached模块),使用python-memcached模块链接Memcache CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': 'Memcache服务器', # 同时链接多台Memcache服务器 'LOCATION': ['服务器1', '服务器2', ...] # 多台Memcache服务器权重设置 'LOCATION': [('服务器1', 10), ('服务器2', 11), ...] } } # Memcache(pylibmc模块),使用pylibmc模块链接Memcache CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache', 'LOCATION': 'Memcache服务器', # 同时链接多台Memcache服务器 'LOCATION': ['服务器1', '服务器2', ...] # 多台Memcache服务器权重设置 'LOCATION': [('服务器1', 10), ('服务器2', 11), ...] } }
Django也可使用Redis缓存,但必须依赖django-redis模块(使用pip安装):
CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "CONNECTION_POOL_KWARGS": {"max_connections": 100} "PASSWORD": "密码", } } }
Django中提供了“信号调度”,即容许在某些动做发生时,执行一些特定的操做。
内置信号:
Model signals pre_init # django的modal执行其构造方法前,自动触发 post_init # django的modal执行其构造方法后,自动触发 pre_save # django的modal对象保存前,自动触发 post_save # django的modal对象保存后,自动触发 pre_delete # django的modal对象删除前,自动触发 post_delete # django的modal对象删除后,自动触发 m2m_changed # django的modal中使用m2m字段操做第三张表(add,remove,clear)先后,自动触发 class_prepared # 程序启动时,检测已注册的app中modal类,对于每个类,自动触发 Management signals pre_migrate # 执行migrate命令前,自动触发 post_migrate # 执行migrate命令后,自动触发 Request/response signals request_started # 请求到来前,自动触发 request_finished # 请求结束后,自动触发 got_request_exception # 请求异常后,自动触发 Test signals setting_changed # 使用test测试修改配置文件时,自动触发 template_rendered # 使用test测试渲染模板时,自动触发 Database Wrappers connection_created # 建立数据库链接时,自动触发
使用内置信号:
# 能够新建目录或py文件,而后在工程文件夹下的__init__.py中导入,这样在Django运行时就可使信号生效 from django.core.signals import request_finished from django.core.signals import request_started from django.core.signals import got_request_exception from django.db.models.signals import class_prepared from django.db.models.signals import pre_init, post_init from django.db.models.signals import pre_save, post_save from django.db.models.signals import pre_delete, post_delete from django.db.models.signals import m2m_changed from django.db.models.signals import pre_migrate, post_migrate from django.test.signals import setting_changed from django.test.signals import template_rendered from django.db.backends.signals import connection_created def callback(sender, **kwargs): pass 信号.connect(callback) # 也可使用装饰器来运行信号 from django.dispatch import receiver @receiver(信号) def my_callback(sender, **kwargs): pass
自定义信号:
# 定义信号 import django.dispatch xxx = django.dispatch.Signal(providing_args=[参数1, 参数2, ...]) # 注册信号 def callback(sender, **kwargs): pass xxx.connect(callback) # 触发信号,因为内置信号的触发者已集成在Django中,因此会自动调用,而自定义信号则须要开发者在须要的位置触发 from 路径 import xxx xxx.send(sender='触发者', 参数1 = , 参数2 = , ...)