【问题标题】:Django models - how to thinkDjango 模型 - 如何思考
【发布时间】:2017-05-14 05:22:07
【问题描述】:

同学们,

随着我的系统变得越来越复杂,我需要帮助来思考如何实现复杂的行为。我会解释:

我有三个模型:Purchase、PurchaseDetails 和 Stock。

型号如下:

class Purchase(models.Model):
    def __str__(self):
        return  self.parceiro_pj.razao_social + ' em ' + str(self.data) + ": " + str(self.soma)

    parceiro_pj = models.ForeignKey(ParceiroPJ,blank=True, null=True)
    createdat = models.DateTimeField()
    data = models.DateField(auto_now=True)
    soma = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

class PurchaseDetails(models.Model):

    def __str__(self):
        return str(self.parceiro_pj_insumo.insumo.nome) + ' - ' + str(self.quantidade) + ' - ' + str(self.createdat)

    purchase = models.ForeignKey(Purchase)
    parceiro_pj_insumo = models.ForeignKey(ParceiroPJInsumo)
    quantidade = models.IntegerField(blank=False, null=False)
    createdat = models.DateField(auto_now=True)

    def save(self, *args, **kwargs):
        super(PurchaseDetail, self).save(*args, **kwargs) # Call the "real" save() method.
        PurchaseDetail.objects.filter(Purchase=self.purchase.id).update(createdat=self.purchase.createdat.date())
        itens = PurchaseDetail.objects.filter(compra=self.purchase.id)
        valor = 0
        for item in itens:
            valor = valor + (item.parceiro_pj_insumo.preco * item.quantidade)

            no_estoque = Estoque.objects.get(insumo=item.parceiro_pj_insumo.insumo.id)
            unidade = Unidade.objects.get(nome=item.parceiro_pj_insumo.insumo.unidade.nome)
            qt = no_estoque.quantidade + item.quantidade
            volume_peso = no_estoque.volume_peso + (item.quantidade * item.parceiro_pj_insumo.insumo.volume_peso)
            Stock.objects.filter(insumo=item.parceiro_pj_insumo.insumo).update(quantidade=qt, unidade=unidade, volume_peso=volume_peso, updatedat=self.purchase.createdat.date())

        Purchase.objects.filter(pk=self.purchase.id).update(soma=valor)
        Purchase.objects.filter(pk=self.purchase.id).update(data=self.purchase.createdat.date())

class Stock(models.Model):

    def __str__(self):
        return str(self.insumo.nome) + '(' + str(self.insumo.marca.nome) +  ')' + ' - ' + str(self.quantidade)

    insumo = models.OneToOneField(Insumo)
    quantidade = models.IntegerField(blank=True, null=True)
    unidade = models.ForeignKey(Unidade, blank=True, null=True)
    volume_peso = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True) 
    updatedat = models.DateField(auto_now=False, blank=True, null=True)

有相关的: a) 一次购买有许多购买详情; b) 每个 PurchaseDetail 都会对 Stock 产生影响。对于每个 PurchaseDetail 操作(插入、更改、删​​除),必须更新 Stock。

我知道每次插入 PurchaseDetail 时如何对 Stock 进行更改。但对于 DELETE 和 UPDATE,逻辑似乎要复杂得多。

如果我编辑 PurchaseDetails,它的制作方式,如果我已经在数据库中有一个项目,当我保存 PurchaseDetails 时将再次计算它(此模型嵌入在管理员的购买表单中),导致错误和更新又是股票。

我不知道如何实施正确的做法。

我必须检查它是否是 PurchaseDetail 上的新项目,或者它是否是在更新 Stock 之前已经存在的寄存器,我不知道该怎么做。另外,当我必须删除 PurchaseDetails 并减少 Stock 上的项目时,我不知道 hot tom 实现的情况。

有人可以帮忙吗?

【问题讨论】:

    标签: django-models django-admin


    【解决方案1】:

    您可以考虑探索 Django 信号提供的功能,这将为您提供一种实现此类行为的好方法。信号可以通过__init__()save() 等内置模型方法发送,并且在应用程序的不同区域可能想要使用有关这些类型事件的信息时很有用。

    Django 的一些内置信号包括 pre_save、post_save、pre_delete、post_delete 等;定义和发送您自己的信号也很简单。

    看一个您已有的简化示例,假设您想在每次保存相关的PurchaseDetail 时更新特定的Stock,出于某种原因。您可以定义一个方法,如:

    def update_stock(sender, instance, **kwargs):
        purchase_details_id = instance.id
        # do something here, like update and save a stock
    
    post_save.connect(update_stock, sender=PurchaseDetail)
    

    update_stock 是接收函数,将在保存PurchaseDetail 对象后调用。

    进一步参考: https://docs.djangoproject.com/en/1.10/ref/signals/

    【讨论】:

    • 谢谢韦斯!如果我在 PurchaseDetails 上实现 pre_save 信号,你知道我怎样才能只获取尚未保存的对象吗?
    • 在您的接收器函数中,您可能会根据 PurchaseDetail 发送器键找到要更新的特定对象。
    • 我不清楚该怎么做。您能否更清楚地说明如何保存新旧对象的差异?
    • @GustavoSooeiro 好吧,您可以检查 self.pk 以查看您的保存方法中的对象是否是新的 if self.pk is None: 如果对象是新的,则为 True
    猜你喜欢
    • 2011-05-13
    • 1970-01-01
    • 1970-01-01
    • 2011-06-11
    • 2020-08-28
    • 1970-01-01
    • 2011-06-16
    • 1970-01-01
    相关资源
    最近更新 更多