欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入理解Django-Signals信號量

 更新時間:2019年02月19日 09:27:45   作者:二十一  
這篇文章主要介紹了深入理解Django-Signals信號量,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

定義Signals

Django自身提供了一些常見的signal,用戶本身也可以定義自己需要的signal

定義signal很簡單,只需要實例化一個Signal實例即可

實例化Signal時,可以傳入關鍵詞參數(shù)providing_args, providing_args是一個列表,列表中定義了當前signal調(diào)用send方法時可以傳入的參數(shù)。

# django.core.signals.py

from django.dispatch import Signal

request_started = Signal(providing_args=["environ"])
request_finished = Signal()
got_request_exception = Signal(providing_args=["request"])
setting_changed = Signal(providing_args=["setting", "value", "enter"])

其中Signal的初始化也比較簡單,就是為實例化的signal定義一個線程鎖

class Signal(object):
  def __init__(self, providing_args=None, use_caching=False):
    self.receivers = []
    if providing_args is None:
      providing_args = []
    self.providing_args = set(providing_args)
    self.lock = threading.Lock()
    self.use_caching = use_caching
    # For convenience we create empty caches even if they are not used.
    # A note about caching: if use_caching is defined, then for each
    # distinct sender we cache the receivers that sender has in
    # 'sender_receivers_cache'. The cache is cleaned when .connect() or
    # .disconnect() is called and populated on send().
    self.sender_receivers_cache = weakref.WeakKeyDictionary() if use_caching else {}
    self._dead_receivers = False

定義Signal處理函數(shù)

Signal處理函數(shù)是一個函數(shù)或者是一個實例的方法,并且必須滿足下面條件:

  1. hashable
  2. 可以接收關鍵詞參數(shù)

其中處理函數(shù)必須包含的關鍵詞參數(shù)有兩個:

  • signal,要接收的Signal實例
  • sender,要接收的Signal觸發(fā)者
# django.db.__init__.py

from django.core import signals
from django.db.utils import ConnectionHandler

connections = ConnectionHandler()


def reset_queries(**kwargs):
  for conn in connections.all():
    conn.queries_log.clear()
signals.request_started.connect(reset_queries)


def close_old_connections(**kwargs):
  for conn in connections.all():
    conn.close_if_unusable_or_obsolete()
signals.request_started.connect(close_old_connections)
signals.request_finished.connect(close_old_connections)

處理函數(shù)綁定Signal

django提供了兩種方法可以將Signal的處理函數(shù)和Signal實例進行綁定:

  • 手動調(diào)用connect方法
  • 使用裝飾器receiver

其實裝飾器receiver最終還是調(diào)用了connect方法將處理函數(shù)和Signal實例進行綁定

Signal類的connect方法定義如下:

class Signal(object):

  ...
  
  def connect(self, receiver, sender=None, weak=True, dispatch_uid=None):
    from django.conf import settings

    # If DEBUG is on, check that we got a good receiver
    if settings.configured and settings.DEBUG:
      assert callable(receiver), "Signal receivers must be callable."

      # Check for **kwargs
      if not func_accepts_kwargs(receiver):
        raise ValueError("Signal receivers must accept keyword arguments (**kwargs).")

    if dispatch_uid:
      lookup_key = (dispatch_uid, _make_id(sender))
    else:
      lookup_key = (_make_id(receiver), _make_id(sender))

    if weak:
      ref = weakref.ref
      receiver_object = receiver
      # Check for bound methods
      if hasattr(receiver, '__self__') and hasattr(receiver, '__func__'):
        ref = WeakMethod
        receiver_object = receiver.__self__
      if six.PY3:
        receiver = ref(receiver)
        weakref.finalize(receiver_object, self._remove_receiver)
      else:
        receiver = ref(receiver, self._remove_receiver)

    with self.lock:
      self._clear_dead_receivers()
      for r_key, _ in self.receivers:
        if r_key == lookup_key:
          break
      else:
        self.receivers.append((lookup_key, receiver))
      self.sender_receivers_cache.clear()

每個信號量根據(jù)receiver和sender都可以獲取一個lookup_key可以唯一的標志一個Signal和其處理方法, 當調(diào)用Signal實例的connect方法時,會判斷綁定的處理函數(shù)是否已經(jīng)在自身receivers中,如果存在則不會重復注冊

發(fā)送Singal

有了前面定義的Signal實例,以及定義的Signal實例處理方法,經(jīng)過處理函數(shù)綁定Signal實例后就可以在必要的地方發(fā)送信號, 然后讓綁定的處理函數(shù)處理了。

# django.core.handlers.wsgi.py

from threading import Lock

from django.core import signals
from django.core.handlers import base

 

class WSGIHandler(base.BaseHandler):

  ...

  def __call__(self, environ, start_response):

    ...
    
    signals.request_started.send(sender=self.__class__, environ=environ)
    
    ...

信號量最為Django的一個核心知識點,在項目中很少有使用到,所以很多人都不了解或者沒聽過過(包括我)。簡單來說就是在進行一些操作的前后我們可以發(fā)出一個信號來獲得特定的操作,這些操作包括

django.db.models.signals.pre_save&django.db.models.signals.post_save
在模型 save()方法調(diào)用之前或之后發(fā)送。

django.db.models.signals.pre_delete&django.db.models.signals.post_delete
在模型delete()方法或查詢集的delete() 方法調(diào)用之前或之后發(fā)送。

django.db.models.signals.m2m_changed
模型上的 ManyToManyField 修改時發(fā)送。

django.core.signals.request_started&django.core.signals.request_finished
Django開始或完成HTTP請求時發(fā)送。

其他細致的知識點,大家可以點鏈接查看,直接通過一個例子解釋:

在自定義用戶模型類的時候,在后臺添加用戶數(shù)據(jù)因為使用了自定義模型類的create所以密碼會以明文保存,接下來使用信號量方式在保存后馬上修改密碼解決。(網(wǎng)上一個項目的例子)

users/signals.py

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()


# post_save:上面七大方法之一:在模型保存之后的操作
# sender: 發(fā)出信號的model
@receiver(post_save, sender=User)
def create_user(sender, instance=None, created=False, **kwargs):
  """
  sender:模型類。
  instance:保存的實際實例。
  created:如果創(chuàng)建了新記錄True。
  update_fields:Model.save()要更新的字段集,如果沒有傳遞則為None
  """
  if created:
    password = instance.password
    # instance相當于user
    instance.set_password(password)
    instance.save()

users/apps.py

from django.apps import AppConfig


class UsersConfig(AppConfig):
  name = 'users'
  verbose_name = '用戶管理'

  def ready(self):
  """使用ready加載,否則不生效"""
    import users.signals

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Python 記錄日志的靈活性和可配置性介紹

    Python 記錄日志的靈活性和可配置性介紹

    這篇文章給大家介紹了關于日志記錄庫的靈活性和可配置性,目的在于證明它如何設計的,對python 日志記錄相關知識感興趣的朋友跟隨腳本之家小編一起學習吧
    2018-02-02
  • 一文搞懂Python的hasattr()、getattr()、setattr()?函數(shù)用法

    一文搞懂Python的hasattr()、getattr()、setattr()?函數(shù)用法

    python中的getattr()、setattr()、hasattr()函數(shù)均是對類屬性或方法的操作,其中getattr()用于獲取類或?qū)嵗兄付ǚ椒ǐ@取屬性的值,setattr()用于設置類或?qū)嵗袑傩曰蚍椒?hasattr()用于判斷類或?qū)嵗惺欠翊嬖谥付ǖ膶傩曰蚍椒?本文通過例子給大家詳解,一起看看吧
    2022-04-04
  • Python面向?qū)ο笾^承和多態(tài)用法分析

    Python面向?qū)ο笾^承和多態(tài)用法分析

    這篇文章主要介紹了Python面向?qū)ο笾^承和多態(tài)用法,結(jié)合實例形式分析了Python面向?qū)ο蟪绦蛟O計中繼承與多態(tài)的原理及相關操作技巧,需要的朋友可以參考下
    2019-06-06
  • 在Python中執(zhí)行系統(tǒng)命令的方法示例詳解

    在Python中執(zhí)行系統(tǒng)命令的方法示例詳解

    最近在做那個測試框架的時候發(fā)現(xiàn)對python執(zhí)行系統(tǒng)命令不太熟悉,所以想著總結(jié)下,下面這篇文章主要給大家介紹了關于在Python中執(zhí)行系統(tǒng)命令的方法,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-09-09
  • Python上下文管理器用法及實例解析

    Python上下文管理器用法及實例解析

    這篇文章主要介紹了Python上下文管理器用法及實例解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • Python文件操作類操作實例詳解

    Python文件操作類操作實例詳解

    這篇文章主要介紹了Python文件操作類操作實例代碼,需要的朋友可以參考下
    2014-07-07
  • 淺析Python條件語句中的解密邏輯與控制流

    淺析Python條件語句中的解密邏輯與控制流

    這篇文章主要想來和大家一起探索一下Python條件語句的奇妙世界——解密邏輯與控制流,文中的示例代碼講解詳細,感興趣的小伙伴可以學習一下
    2023-07-07
  • 對python中assert、isinstance的用法詳解

    對python中assert、isinstance的用法詳解

    今天小編就為的就分享一篇對python中assert、isinstance的用法詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • Python中高級語法糖的使用示例詳解

    Python中高級語法糖的使用示例詳解

    Python?是一門簡潔而強大的編程語言,具備許多高級語法糖(syntactic?sugar)功能,本文將介紹一些常見的Python高級語法糖,以及如何使用它們來提高代碼質(zhì)量和開發(fā)效率,需要的小伙伴可以參考下
    2024-01-01
  • python爬取2021貓眼票房字體加密實例

    python爬取2021貓眼票房字體加密實例

    在本篇文章里小編給大家整理的是一篇關于python爬取2021貓眼票房字體加密實例內(nèi)容,有興趣的朋友們可以學習下。
    2021-02-02

最新評論