Django ForeignKey关系中的子模型更新父模型

h5qlskok  于 2023-06-25  发布在  Go
关注(0)|答案(3)|浏览(108)

假设以下模型模式,

父模型:

class Batch(models.Model):
    start = models.DateTimeField()
    end = models.DateTimeField()

众多子模型之一:

class Data(models.Model):
    batch = models.ForeignKey(Batch, on_delete=models.ON_CASCADE)
    timestamp = models.DateTimeField()

我的目标如下:使父模型的起始字段在任何子模型被修改时总是更新。基本上,如果新数据示例的时间戳比开始字段旧,我希望开始字段更新为该示例时间戳值。在删除最早的时间参考点的数据示例的情况下,我希望批处理开始字段更新为第二个最早的。对于结束字段,反之亦然。

d6kp6zgx

d6kp6zgx1#

其中一种可能的方法是添加相关模型的post或pre-save信号,并根据此更新必要的字段。Django信号的官方文档,link。我想添加另一个link,我见过的关于Django信号的最好的博客文章之一。

编辑André Guerra响应

一个最简单的方法来做一个get调用,并带来批处理示例。我想说的是

@receiver(post_save,sender=Data)
def on_batch_child_saving(sender,instance,**kwargs):
    batch_instance = Batch.objects.get(pk=instance.batch)
    if (instance.timestamp < batch_instance.start): 
        batch_instance.start = instance.timestamp
        batch_instance.save()

    elif (instance.timestamp > batch_instance.end):
        batch_instance.end = instance.timestamp
        batch_instance.save()
92vpleto

92vpleto2#

根据Shakil的建议,我得出了这样的结论:(我在这里的疑问是如何保存父模型)

@receiver(post_save,sender=Data)
def on_batch_child_saving(sender,instance,**kwargs):
    if (instance.timestamp < instance.batch.start): 
        instance.batch.start = instance.timestamp
        instance.batch.save()

    elif (instance.timestamp > instance.batch.end):
        instance.batch.end = instance.timestamp
        instance.batch.save()
jjhzyzn0

jjhzyzn03#

在Django中,你可以使用signal来更新父节点。为此,您需要创建一个信号来侦听子模型的post_save信号,并发送一个信号来更新父模型。

# models.py

from django.db import models
from django.dispatch import receiver
from django.db.models.signals import post_save

class Batch(models.Model):
    start = models.DateTimeField()
    end = models.DateTimeField()

class Data(models.Model):
    batch = models.ForeignKey(Batch, on_delete=models.ON_CASCADE)
    timestamp = models.DateTimeField()

@receiver(post_save,sender=Data)
def update_batch(sender,instance,**kwargs):
    batch = instance.batch
    if (instance.timestamp < batch.start): 
        batch.start = instance.timestamp

    elif (instance.timestamp > batch.end):
        batch.end = instance.timestamp

    batch.save()

有关更多信息,请参阅此answer

相关问题