装饰django中的模型类在装饰器中保存

时间:2011-10-25 19:10:30

标签: python django django-models decorator

我有几个模型可以将日志数据保存到我的数据库中。我还有一个“最近的事件”应用程序,我想选择哪些模型将数据发送到事件应用程序。我认为装饰器对此有好处,所以我可以将它添加到我想要的模型中:

@logger
class TemperatureLog(models.Model):
    Date = models.DateTimeField(auto_now_add=True)
    Device = models.ForeignKey(TemperatureDevice)
    Data = models.PositiveIntegerField()

这是事件模型,Im使用通用外键:

class Event(models.Model):
    Active = models.BooleanField()
    Queue = models.BooleanField()
    ContentType = models.ForeignKey(ContentType)
    ObjectID = models.PositiveIntegerField()
    Event = generic.GenericForeignKey('ContentType', 'ObjectID')

这是装饰者:

def logger(event):
    def wrap(*args, **kwargs):
        from toolbox.event.models import Event
        event(*args, **kwargs).save()
        myid = event(*args, **kwargs).id
        new = Event(Event=event.objects.get(id=myid))

        if Event.objects.all().filter(Active=True).count() >= 25:
            new.Queue = True
            new.save()

        else:
            new.Active = True
            new.save()

            for item in Event.objects.all().filter(Queue=True):
                item.Queue = False
                item.Active = True
                item.save()

                if  Event.objects.all().filter(Active=True).count() >= 25:
                    break
        return event(*args, **kwargs)

    return wrap

它可以正常工作,它创建事件实例并保存它。我遇到的问题是save()会被调用两次。一个在装饰器中,第二个在实际代码中收集温度日志(因为我不知道哪个应用程序将发送事件,哪些将来或者它们将来可能会发生变化)。所以我想知道是否有一种更优雅的方式来做到这一点。我喜欢装饰器方法,因为我所要做的就是将它添加到模型类中,但我不太相信保存被调用两次。

2 个答案:

答案 0 :(得分:1)

对您的问题的“原则上”回答是考虑使用the pre_save signal built into Django

基本上,您将侦听器函数连接到pre_save信号,在上面的链接中完整记录,您可以修改模型实例上的所需属性。只有在侦听器完成执行后(以及连接到该模型上pre_save的任何其他侦听器),模型实例才会保存到数据库中。

如果我正确理解了您的代码,当且仅当数据库中有25个或更多活动事件记录时,您希望Queue变量设置为True,否则False({1}}与Active相反 - 为什么你需要两个我不明白的布尔值。你可以通过做这样的事情来做信号......

from django.db.signals import pre_save

def update_event_active_queue_status(sender, instance=None, **kwargs):
    if Event.objects.filter(Active=True).count() >= 25:
        instance.Queue = True
    else:
        instance.Active = True
pre_save.connect(update_event_active_queue_status, sender=Event)

你正试图解决的一个单独的问题,我不认为这是正确的地方,当活动事件的数量低于25时,将排队的事件重新激活。我不知道你的确切需求,但我可能已经在cron工作或其他事件管理器上完成,而不是在这里解决。现在,如果没有事件添加到系统中(或以其他方式更改),项目将永远不会被拉出队列。这可能不是你想要的。

当然,你比我更了解你的需求,所以我的建议就是一丝不苟。

答案 1 :(得分:0)

如何为所有模型使用post_save信号

def log_saved_event(sender, instance, signal, *args, **kwargs):
    # handle Event class
    pass

from django.db.models import signals
from django.db import models

for m in models.get_models():
    signals.post_save.connect(log_saved_event, sender=m)