среда, 8 августа 2012 г.

Декоратор для автоматической регистрации сигналов Django

Давно наткнулся в сети на хороший сниппет, позволяющий декоратором навесить сигнал сохранения модели на метод класса модели Django. Уже и не помню, где его нашел, поэтому просто приведу чуть-чуть доработанный мной сниппет:

from functools import wraps
from django.db.models.signals import pre_save
from django.db.models.signals import post_save

def autoconnect_signals(cls):
    """ 
    Class decorator that automatically connects pre_save/post_save signals on 
    a model class to its pre_save_handler()/post_save_handler() methods.
    """
    def connect(signal, func):
        cls.func = staticmethod(func)
        @wraps(func)
        def wrapper(sender, *args, **kwargs):
            return func(kwargs.get('instance'), args, kwargs)

        signal.connect(wrapper, sender=cls)
        return wrapper

    if hasattr(cls, 'pre_save_handler'):
        cls.pre_save_handler = connect(pre_save, cls.pre_save_handler)

    if hasattr(cls, 'post_save_handler'):
        cls.post_save_handler = connect(post_save, cls.post_save_handler)
    
    return cls

Пользоваться декоратором просто. Создаете модель, в ней делаете методы pre_save_handler и/или post_save_handler и оборачиваете класс декоратором:

@autoconnect_signals    
class Book(models.Model):    
    
    #...
    name = models.SlugField(_("Name"), max_length = 150, unique = True)

    def pre_save_handler(self,*args, **kwargs):
        u"""Сигнал, получаемый перед сохранением модели."""
        print self.name #в self передается сам инстанс модели.
                        #Остальное есть в аргументах.

    def post_save_handler(self,*args, **kwargs):
        u"""Сигнал, получаемый после сохранения модели."""
        print self.name

Вот и все. pre_save_handler и post_save_handler сами вызовуться по соответствующим сигналам сохранения модели.


Комментариев нет:

Отправить комментарий