在 django 中装饰模型类并在装饰器中保存
我有几个模型可以将日志数据保存到我的数据库中。我还有一个“最近事件”应用程序,我想选择哪些模型将数据发送到事件应用程序。我认为装饰器对此很有用,所以我可以将它添加到我想要的模型中:
@logger
class TemperatureLog(models.Model):
Date = models.DateTimeField(auto_now_add=True)
Device = models.ForeignKey(TemperatureDevice)
Data = models.PositiveIntegerField()
这是事件模型,我使用通用外键:
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() 将被调用两次。一个在装饰器中,第二个在收集温度日志的实际代码中(因为我不会提前知道哪些应用程序将发送事件,哪些不会发送事件,或者它们将来是否可能发生变化)。所以我想知道是否有更优雅的方法来做到这一点。我喜欢装饰器方法,因为我所要做的就是将其添加到模型类中,但我不太相信 save 被调用两次。
I have several models that save log data to my database. I also have a "recent events" app and I would like to choose which models send data to the events app. I thought a decorator would be good for this, so I could just add it to the models I want:
@logger
class TemperatureLog(models.Model):
Date = models.DateTimeField(auto_now_add=True)
Device = models.ForeignKey(TemperatureDevice)
Data = models.PositiveIntegerField()
Here is the events model, Im using generic foreign keys:
class Event(models.Model):
Active = models.BooleanField()
Queue = models.BooleanField()
ContentType = models.ForeignKey(ContentType)
ObjectID = models.PositiveIntegerField()
Event = generic.GenericForeignKey('ContentType', 'ObjectID')
And here is the decorator:
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
It works as it should, it creates the event instance and saves it. The problem that I have is that save() would be called twice. One in the decorator and the second in the actual code that collects the temperature logs (since I wont know ahead of time which apps will send events and which wont or if they might change in the future). So I wonder if there is a more elegant way to do this. I like the decorator approach since all I have to do is add it to the model class, but I am not very convinced of having save being called twice.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对您问题的“原则上”回答是考虑使用
pre_save 内置于 Django 的信号
。
基本上,您将侦听器函数连接到
pre_save
信号,完整记录在上面的链接中,并且您可以修改模型实例上所需的属性。仅当您的侦听器完成执行(以及连接到该模型上的pre_save
的任何其他侦听器)后,模型实例才会保存到数据库中。如果我正确理解您的代码,当且仅当数据库中有 25 个或更多活动事件记录时,您希望将
Queue
变量设置为True
,并且False
否则(与Active
相反 - 为什么你需要两个布尔值,我不明白)。您可以通过执行以下操作来使用信号来做到这一点...您正在尝试解决的一个单独的问题,我认为这不是正确的地方,是将排队的事件移回活动状态,当数量达到活动事件数低于 25。我不知道您的确切需求,但我可能会在 cron 作业或其他事件管理器上完成此操作,而不是在此处解决。现在,如果没有事件添加到系统中(或以其他方式更改),则项目永远不会从队列中拉出。这可能不是你想要的。
当然,您比我更了解您的需求,所以请对我的建议持保留态度。
The "in principle" response to your question is to consider using the
pre_save
signal built into Django.Basically, you connect a listener function to the
pre_save
signal, documented in full at the link above, and you can modify the desired properties on your model instance. Only after your listener finishes executing (as well as any other listeners connected topre_save
on that model) will the model instance be saved to the database.If I understand your code correctly, you want your
Queue
variable set toTrue
if and only if there are 25 or more active event records in the database, andFalse
otherwise (with the opposite forActive
-- why you need two booleans I don't understand). You could do that with signals by doing something like this...A separate problem that you're trying to solve, and I don't think this is the right place for it, is moving queued events back to active when the number of active events falls below 25. I don't know your exact needs, but I'd probably have that done on a cron job or by some other event manager, rather than being addressed here. Right now, if no events are added into the system (or changed in some other way), items would never be pulled out of queue. That's probably not what you want.
Of course, you know your needs better than I do, so take my recommendations with a grain of salt.
对所有模型使用 post_save 信号怎么样
How about using post_save signal for all models