我正在尝试添加一个递增整数,在这种情况下,此序列号应为[1,n],其中n是给定计划中的序列数。
由于序列会定期更新,我想知道循环浏览以下内容的最有效方法
Sequence.objects.filter(schedule=schedule).order_by('start', 'id')
,并为每个序列分配递增编号。另外,如果我希望每次创建,删除新序列或更新start
字段时都运行该方法,那么在哪里是实现此方法的理想场所。我一直在考虑save()
和delete()
方法,但是当序列中仅其他字段更新时,我不希望更新。
这是我的序列模型
class Sequence(models.Model):
number = models.PositiveIntegerField(
verbose_name='sequence number',
help_text='auto incrementing sequence number',
)
schedule = models.ForeignKey(
to=Schedule,
verbose_name='schedule',
on_delete=models.CASCADE,
related_name='sequences',
help_text='schedule primary key',
)
start = models.DateTimeField(
verbose_name='start date',
help_text='sequence starting datetime',
)
end = models.DateTimeField(
verbose_name='end date',
help_text='sequence ending datetime',
)
答案 0 :(得分:1)
好吧,您可以(不用说“应该”)为此使用Django signals。
Django包括一个“信号分配器”,当动作在框架中的其他位置发生时,该信号分配器可帮助脱钩的应用程序得到通知。简而言之,信号允许某些发送者通知一组接收者已经采取了某些措施。 当许多代码片段可能对同一事件感兴趣时,它们特别有用。
然后您可以根据Sequence
模型正在发送的信号(post_save,pre_save,pre_delete等)使用函数(接收器)进行更新。
为此,您不应覆盖save
或delete
。您的逻辑涉及对多个实例的更改,因此您应相对于单个实例保留保存和删除操作。
另一方面,您可以使用F表达式来有效地更新序列实例。
您会在文档中找到一个很好的例子。
https://docs.djangoproject.com/en/2.1/ref/models/expressions/#f-expressions
好吧,在最初的答案中,我指出了要走的路,现在我将向您展示整个过程,希望您能自己弄清楚。
我尝试使用信号,但得出的结论是这是错误的方法。信号将为每个save()触发。因此触发了无限循环。
这不是错误的方法,您使用了错误的信号/实现;)。
根据您的要求,我可以告诉您存在对应关系:
update sequence instance (save) ---> do not change indices
delete sequence instance ---> update indices
create sequence instance ---> add incremented index
因此,我们有信号delete
和信号post_save,它接收布尔值作为第三个参数,说明实例是已创建还是刚刚更新(您读了我共享的链接吗?和你在一起?)。
然后...
Sequence
实例时更新索引:@receiver(delete, sender=Sequence)
def deletion_handler(sender, instance, **kwargs):
# Since number is incremental we only must update
# those that are after the instance being deleted.
number = instance.number
sequences_for_update = Sequence.objects.filter(number__gt=number)
# Decrement 1 to all sequences after number. No for loop.
sequences_for_update.update(number=F('number') - 1)
@receiver(post_save, sender=Sequence)
def creation_handler(sender, instance, created, **kwargs):
if created:
# We only care about created instances (this avoid the infinite
# loop you're talking about).
# Now take the last number.
instance.number = Sequence.objects.aggregate(last=Max('number'))['last'] + 1
instance.save()