Hello I'm trying to make on update trigger in Django Model.

Model.py

class Item(models.Model):
    status_type = (
        ('a','Active'),
        ('d','Deactive')
    )
    code = models.CharField(max_length=100, null=True, blank=True, unique=True)
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    gsts = models.ForeignKey(Gst, on_delete=models.CASCADE)
    sgst = models.DecimalField(max_digits=10, decimal_places=2,null=True,blank=True)
    cgst = models.DecimalField(max_digits=10, decimal_places=2,null=True,blank=True)
    net_amount = models.DecimalField(max_digits=10, decimal_places=2,null=True,blank=True)
    status = models.CharField(max_length=1, choices=status_type, default = 'a')
    create_at = models.DateField(auto_now_add=True)
    update_at = models.DateField(auto_now=True)
    create_by = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.name
    
def ItemGenerator(sender, instance, created, *args, **kwargs):
    if created:
        id = instance
        query = Item.objects.get(id = int(id.id))
        #gst calculation
        gst_cal = query.price * query.gsts.gst/100
        #net amount calculation
        net_amounts = query.price + gst_cal        
        #item number generate
        temp_count = Item.objects.all().count()
        no = str('ITEM') + '/' +str(temp_count)
        query = Item.objects.filter(id = id.id).update(code = str(no), cgst = round(gst_cal/2), sgst=round(gst_cal/2), net_amount = round(net_amounts))

When I'm insert to the data post_save signal is call and my price and gst calculation save into data base but problem is that when I'm update the record post_save signal is not working

推荐答案

这不是错误,这是预期的行为,您的if created会判断您是否为created对象运行信号,因此它不会在记录更新的情况下运行.

您可以使用以下命令省略此参数:

def ItemGenerator(sender, instance, created, *args, **kwargs):
    if created:
        temp_count = Item.objects.all().count()
        no = str('ITEM') + '/' + str(temp_count)
    else:
        no = instance.code
    gst_cal = instance.price * instance.gsts.gst / 100
    net_amounts = instance.price + gst_cal
    query = Item.objects.filter(pk=instance.pk).update(
        code=no,
        cgst=round(gst_cal / 2),
        sgst=round(gst_cal / 2),
        net_amount=round(net_amounts),
    )

但信号是not是必要的.信号通常是avoid的模式.例如,信号don't在批量更新或批量创建的情况下运行,很容易导致无限递归,等等.这里是我写的an article个,讨论了信号的潜在问题.

更糟糕的是,这只是data duplication,这意味着您重复相同的数据,但形状或形式不同.

from django.conf import settings


class Item(models.Model):
    status_type = (('a', 'Active'), ('d', 'Deactive'))
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    gsts = models.ForeignKey(Gst, on_delete=models.CASCADE)
    status = models.CharField(max_length=1, choices=status_type, default='a')
    create_at = models.DateField(auto_now_add=True)
    update_at = models.DateField(auto_now=True)
    create_by = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE
    )

    @property
    def code(self):
        return f'ITEM/{type(self).objects.filter(create_at__lt=self.create_at).count()}'

    @property
    def cgst_unround(self):
        if not hasattr(self, '_cgst'):
            self._cgst = self.price * self.gsts.gsts / 100
        return self._cgst

    @property
    def cgst(self):
        return round(self.cgst_unround, 2)

    @property
    def sgst(self):
        return self.cgst

    @property
    def net_amount(self):
        return round(self.price + self.gst)

    def __str__(self):
        return self.name

这将确定值when needed,因此我们可以使用some_item.net_amount,如果是这样,它将获取.gsts并进行适当的计算.因此,这也将返回一个不同的值,如果您更改.price或例如.gsts中的.gst,这更可靠:如果您更改Gst对象的gst,信号将不会为Item运行,尽管net_amount依赖于该更改,只在需要时计算它,这不会是问题.

如果您需要确定大量对象的.cgst.sgst,这可能会导致所谓的N+1问题.通过在计算之前 Select 相关的.gsts项,我们可以省略这一点:

Item.objects.select_related('gsts')

Django相关问答推荐

Django/SendGrid-密码重置-发件人地址与验证的发件人身份不匹配.";

如何在Django REST框架中使用FactoryBoy创建不同的项目

模仿没有像预期的那样工作(Django)

如何在Django模板中为无效词典查找打开异常?

测试 - 两个类共享相同的登录代码,但它只能在一个类中工作

Django中用于外键的嵌套循环

如何将多个模型添加到单个列表视图?

int_list_validator在 Django 表单中不起作用

Django 表单字段必填和可选配置

Django 模型将外键设置为另一个模型的字段

magic有什么问题?

django excel xlwt

Django - 无法为具有动态 upload_to 值的 ImageField 创建迁移

Django查询否定

升级到 Django 1.8 后提供的固定默认值

django 我们可以在预取相关模型上 Select 一个字段吗?

Python/Django - 避免在源代码中保存密码

为什么我的 Django 单元测试不知道安装了 MessageMiddleware?

在 django 中获取空查询集的类名

获取'str'对象在Django中没有属性'get'