保存mod时合并/删除多个关系中的元素(使用through表)

2024-06-01 02:53:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在开发一个应用程序来管理餐馆的命令。 由于这些命令可以在用餐者中演变,为了更清楚,我想合并包含相同产品的命令行。例如,如果您命令2个bucket of chicken,然后再命令另一个bucket of chicken,我希望最终的命令模型实例只包含一行(bucket of chicken,3),而不是两行

我有一个函数(fusion_atoms),它检测相似的线并合并它们。我尝试在命令模型的save方法中调用它,也尝试在pre_save和post_save信号中调用它。它不起作用。 我是python和django的高手,我认为我做得不对

models.py:

class Command_Atom(models.Model):
    command = models.ForeignKey("Command", on_delete=models.CASCADE)
    produit = models.ForeignKey(Produit, on_delete=models.CASCADE)
    quantite = models.PositiveSmallIntegerField(default=1)
    @property
    def total(self):
        return self.produit.prix * self.quantite

class Command (models.Model):
    client = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    table = models.PositiveSmallIntegerField(default=0)
    produits = models.ManyToManyField(Produit, through="Command_Atom")

    @property
    def atoms(self):
        return Command_Atom.objects.filter(command_id=self.id)

    def fusion_atoms(self):
        lines = self.atoms.all().order_by('produit','prod_options')
        i = 1
        current_line = lines[0]
        to_be_deleted = []
        while i < len(lines):
            if current_line.produit == lines[i].produit:
                print('merge')
                current_line.quantite += lines[i].quantite
                current_line.save()
                to_be_deleted.append(lines[i])
            else:
                current_line = lines[i]
            i += 1
        for l in to_be_deleted:
            l.delete()

    def save(self):
        self.fusion_atoms()
        super(Command,self).save()

signals.py:

@receiver(pre_save, sender=Command_atom)
def presave_atom(sender, **kwargs):
    instance = kwargs['instance']
    print("pre_save %s" % instance)

@receiver(post_save, sender=Command_Atom)
def postsave_Command(sender, **kwargs):
    instance = kwargs['instance']
    print("post_save %s" % instance)

@receiver(pre_save, sender=Command)
def presave_note(sender, **kwargs):
    instance = kwargs['instance']
    #instance.fusion_atoms()
    print("pre_save %s" % instance)

@receiver(post_save, sender=Command)
def postsave_note(sender, **kwargs):
    instance = kwargs['instance']
    #instance.fusion_atoms()
    print("post_save %s" % instance)

我发现问题在于命令模型的pre_save和post_save方法是在实际保存/更新manytomanyfield的对象之前执行的,因此即使fusion_atom方法完成了它的工作,它首先对尚未更新的值进行操作,(因为命令行在命令保存后会更新)其次,保存原子时会恢复这些更改

换句话说,在这个过程中发生了一些事情,但最终的结果是什么都没有改变:-)

为什么在保存所有字段之前调用post_save信号?这看起来很不一致(因为有了这个奇妙的工具)

有没有办法在整个保存过程结束时调用融合方法? M2M字段的元素何时全部保存的信号

还是有完全其他的方法


Tags: 方法instance命令selfmodelssavedefpost