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/