Django信号量回顾及drf信号量常用操作
一.在写接口视图时,保存/删除/更新数据前后需要对序列化后的数据进行处理的方法:
1.重写mixins.CreateModelMixin中恩的create()函数或perform_create()函数:
不足:代码分离性不好,冗杂
.......
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user=self.perform_create(serializer)
re_dict=serializer.data
payload=jwt_payload_handler(user)
re_dict['token']=jwt_encode_handler(payload)
re_dict['name']=user.name if user.name else user.username
headers = self.get_success_headers(serializer.data)
return Response(re_dict, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
'''
重载CreateModelMixin中的函数实现收藏加一,也可用信号量实现(代码分离性好)
:param serializer:
:return:
'''
instance=serializer.save()
goods=instance.goods
goods.fav_num+=1
goods.save()
def perform_destroy(self, instance):
# 重载DestroyModelMixin中的函数实现收藏减一, 也可用信号量实现(代码分离性好)
instance=instance.delete()
goods=instance.goods
goods.fav_num-=1
goods.save()
2.信号量实现(新建signals.py在该app下方便管理):
2.1用户密码更新的信号量:
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth import get_user_model User=get_user_model()
#通过信号接收修改用户密码,加密
@receiver(post_save, sender=User)
def create_user(sender, instance=None, created=False, **kwargs):
#create判断是否是新建
if created:
password=instance.password
instance.set_password(password)
instance.save()
#在app下配置信号量
from django.apps import AppConfig class UsersConfig(AppConfig):
name = 'users'
verbose_name='用户管理'
#配置信号
def ready(self):
import users.signals
2.2收藏功能的信号量:
from django.db.models.signals import post_save,post_delete
from django.dispatch import receiver from .models import UserFav # 通过信号实现收藏加一
@receiver(post_save, sender=UserFav)
def create_userfav(sender, instance=None, created=False, **kwargs):
if created:
goods = instance.goods
goods.fav_num += 1
goods.save() # 通过信号实现收藏减一
@receiver(post_delete, sender=UserFav)
def delete_userfav(sender, instance=None, created=False, **kwargs):
goods = instance.goods
goods.fav_num -= 1
goods.save()
from django.apps import AppConfig class UserOperationConfig(AppConfig):
name = 'user_operation'
verbose_name='用户操作管理' def ready(self):
import user_operation.signals
二.常用信号(均通过send()方法发送)
1.pre_init(
django.db.models.signals.
pre_init):
每当您实例化Django模型时,此信号都会在模型__init__()
方法的开头发送。
使用此信号发送的参数:
sender
- 刚创建实例的模型类。
args
- 传递给的位置参数列表
__init__()
: kwargs
- 传递给关键字参数的字典
__init__()
:
例如,教程有这一行:
p = Poll(question="What's up?", pub_date=datetime.now())
发送给pre_init
处理程序的参数是:
sender | Poll (班级本身) |
args | [] (一个空列表,因为没有传递给位置参数__init__() 。) |
kwargs | {'question': "What's up?", 'pub_date':datetime.now()} |
2.post_init(
django.db.models.signals.
post_init):
和pre_init一样,但是这个__init__()
方法在方法完成时发送。
使用此信号发送的参数:
sender
- 如上所述:刚创建实例的模型类。
instance
- 刚刚创建的模型的实际实例。
3.pre_save(
django.db.models.signals.
pre_save):
这是在模型save()
方法的开头发送的。
使用此信号发送的参数:
sender
- 模型类。
instance
- 正在保存的实际实例。
raw
- 布尔值;
True
如果模型完全按照提供的方式保存(即加载夹具时)。不应该查询/修改数据库中的其他记录,因为数据库可能尚未处于一致状态。 using
- 正在使用的数据库别名。
update_fields
- 要传递给更新的字段集
Model.save()
,或者None
如果update_fields
未传递给它save()
。
4.post_save(
django.db.models.signals.
post_save):
使用此信号发送的参数:
sender
- 模型类。
instance
- 正在保存的实际实例。
created
- 布尔值;
True
如果创建了新记录。 raw
- 布尔值;
True
如果模型完全按照提供的方式保存(即加载夹具时)。不应该查询/修改数据库中的其他记录,因为数据库可能尚未处于一致状态。 using
- 正在使用的数据库别名。
update_fields
- 要传递给更新的字段集
Model.save()
,或者None
如果update_fields
未传递给它save()
。
5.pre_delete(
django.db.models.signals.
pre_delete)
在模型的delete()
方法和查询集的方法的开头发送delete()
。
使用此信号发送的参数:
sender
- 模型类。
instance
- 要删除的实际实例。
using
- 正在使用的数据库别名。
6.post_delete(
django.db.models.signals.
post_delete)
喜欢pre_delete
,但是在模型的delete()
方法和查询集的方法 结束时发送 delete()
。
使用此信号发送的参数:
sender
- 模型类。
instance
要删除的实际实例。请注意,该对象将不再位于数据库中,因此请谨慎对待此实例。
using
- 正在使用的数据库别名。
7.m2m_changed(django.db.models.signals.
m2m_changed):
ManyToManyField
在模型实例上更改a 时发送。严格来说,这不是一个模型信号,因为它是由它发送的ManyToManyField
,但由于它补充了 pre_save
/ post_save
和pre_delete
/ post_delete
当跟踪模型的变化时,它包含在这里。
使用此信号发送的参数:
sender
- 中间模型类描述
ManyToManyField
。定义多对多字段时,将自动创建此类; 您可以使用through
多对多字段中的属性访问它 。 instance
- 更新多对多关系的实例。这可以是与之相关
sender
的类的实例,也可以ManyToManyField
是与之相关的类的 实例。 action
一个字符串,指示对关系执行的更新类型。这可以是以下之一:
"pre_add"
"post_add"
将一个或多个对象添加到关系后发送。
"pre_remove"
在从关系中删除一个或多个对象之前发送。
"post_remove"
从关系中删除一个或多个对象后发送。
"pre_clear"
在清除关系之前发送。
"post_clear"
关系清除后发送。
reverse
指示关系的哪一侧被更新(即,是否正在被修改的正向或反向关系)。
model
从关系中添加,删除或清除的对象类。
pk_set
对于
pre_add
,post_add
,pre_remove
和post_remove
的动作,这是一组已被添加到或从关系移除主键值。对于
pre_clear
和post_clear
行动,这是None
。
using
- 正在使用的数据库别名。
8.classprepared(django.db.models.signals.
class_prepared)
每当模型类被“准备好”时发送 - 也就是说,一旦定义了模型并使用Django的模型系统注册了模型。Django在内部使用这个信号; 它通常不用于第三方应用程序。
由于此信号在app注册表填充过程中发送,并 AppConfig.ready()
在app注册表完全填充后运行,因此无法在该方法中连接接收器。一种可能性是连接它们AppConfig.__init__()
,注意不要导入模型或触发对app注册表的调用。
使用此信号发送的参数:
sender
- 刚准备的模型类。
三.管理信号(django-admin发送的信号)
1.pre_migrate(django.db.models.signals.
pre_migrate):
migrate
在开始安装应用程序之前由命令发送。对于缺少models
模块的应用程序,它不会发出。
使用此信号发送的参数:
sender
AppConfig
要迁移/同步的应用程序的实例。app_config
- 与...相同
sender
。 verbosity
指示manage.py在屏幕上打印的信息量。请参阅
--verbosity
旗帜了解详情。侦听的函数
pre_migrate
应根据此参数的值调整它们输出到屏幕的内容。interactive
如果
interactive
是True
,则提示用户在命令行上输入内容是安全的。如果interactive
是False
,侦听此信号的功能不应尝试提示任何内容。例如,
django.contrib.auth
应用程序只提示,当创建一个超级用户interactive
是True
。using
- 命令将在其上运行的数据库的别名。
plan
- Django 1.10中的新功能。
将用于迁移运行的迁移计划。虽然该计划不是公共API,但这允许在必要时了解计划的极少数情况。计划是两元组的列表,第一项是迁移类的实例,第二项显示迁移是回滚(
True
)还是应用(False
)。 apps
- Django 1.10中的新功能。
Apps
在迁移运行之前包含项目状态的实例。应该使用它来代替全局apps
注册表来检索要对其执行操作的模型。2.post_migrate(
django.db.models.signals.
post_migrate):
在结束时发送
migrate
(即使没有运行迁移)和flush
命令。对于缺少models
模块的应用程序,它不会发出 。此信号的处理程序不得执行数据库模式更改,因为这样做可能会导致
flush
命令在migrate
命令期间运行时失败 。使用此信号发送的参数:
sender
AppConfig
刚刚安装的应用程序的实例。app_config
- 与...相同
sender
。 verbosity
指示manage.py在屏幕上打印的信息量。请参阅
--verbosity
旗帜了解详情。侦听的函数
post_migrate
应根据此参数的值调整它们输出到屏幕的内容。interactive
如果
interactive
是True
,则提示用户在命令行上输入内容是安全的。如果interactive
是False
,侦听此信号的功能不应尝试提示任何内容。例如,
django.contrib.auth
应用程序只提示,当创建一个超级用户interactive
是True
。using
- 用于同步的数据库别名。默认为
default
数据库。 plan
- Django 1.10中的新功能。
用于迁移运行的迁移计划。虽然该计划不是公共API,但这允许在必要时了解计划的极少数情况。计划是两元组的列表,第一项是迁移类的实例,第二项显示迁移是回滚(
True
)还是应用(False
)。 apps
- Django 1.10中的新功能。
例如,您可以在此处注册回调
AppConfig
:from django.apps import AppConfig
from django.db.models.signals import post_migrate def my_callback(sender, **kwargs):
# Your specific logic here
pass class MyAppConfig(AppConfig):
... def ready(self):
post_migrate.connect(my_callback, sender=self)注意:如果您提供
AppConfig
实例作为sender参数,请确保信号已注册ready()
。AppConfig
对于使用修改集INSTALLED_APPS
(例如,当覆盖设置时)运行的测试,将重新创建s,并且应为每个新AppConfig
实例连接此类信号。
四.请求/响应信号(处理请求时核心框架发出的信号)
1.request_started(
django.core.signals.
request_started):
Django开始处理HTTP请求时发送。
使用此信号发送的参数:
sender
- 处理程序类 - 例如
django.core.handlers.wsgi.WsgiHandler
- 处理请求。
environ
environ
提供给请求的字典。2.request_finished(
django.core.signals.
request_finished):
当Django完成向客户端发送HTTP响应时发送。
使用此信号发送的参数:
sender
处理程序类,如上所述。
3.
got_request_exception(
django.core.signals.
got_request_exception):
只要Django在处理传入的HTTP请求时遇到异常,就会发送此信号。
使用此信号发送的参数:
sender
处理程序类,如上所述。
request
HttpRequest
对象。
五.测试信号(仅在运行测试时发送的信号)
1.setting_changed(django.test.signals.
setting_changed):
当通过django.test.TestCase.settings()
上下文管理器或 django.test.override_settings()
装饰器/上下文管理器更改设置的值时,将发送此信号 。
它实际上发送了两次:当应用新值(“设置”)和恢复原始值(“拆除”)时。使用enter
参数来区分这两者。
您也可以从中导入此信号,django.core.signals
以避免django.test
在非测试情况下导入。
使用此信号发送的参数:
sender
- 设置处理程序。
setting
- 设置的名称。
value
- 更改后的设置值。对于最初不存在的设置,在“拆卸”阶段,
value
是None
。 enter
- 布尔值;
True
如果应用该设置,False
则恢复。
2.template_rendered(d
jango.test.signals.
template_rendered)
在测试系统呈现模板时发送。在Django服务器的正常操作期间不会发出此信号 - 它仅在测试期间可用。
使用此信号发送的参数:
六.数据库包装器(启动数据库连接时由数据库包装程序发送的信号)
1.connection_created(
django.db.backends.signals.
connection_created):
数据库包装器与数据库建立初始连接时发送。如果您要将任何后连接命令发送到SQL后端,这将特别有用。
使用此信号发送的参数:
sender
数据库包装类 - 即 django.db.backends.postgresql.DatabaseWrapper
或django.db.backends.mysql.DatabaseWrapper
等
connection
已打开的数据库连接。这可以在多数据库配置中使用,以区分来自不同数据库的连接信号。
七.详情官方文档:
二到六均摘抄于官方文档,更多具体内容:
https://docs.djangoproject.com/en/1.11/ref/signals/