【问题标题】:FOREIGN KEY constraint failed while trying to delete an object related尝试删除相关对象时 FOREIGN KEY 约束失败
【发布时间】:2021-05-30 09:53:28
【问题描述】:

所以我的应用中有这些模型:

from django.db import models
from accounts.models import Vendedor


class Comissao(models.Model):
    porcentagem = models.FloatField()


    def __str__(self):
        return str(self.porcentagem)


class Venda(models.Model):
    vendedor = models.ForeignKey(Vendedor, on_delete=models.DO_NOTHING)
    comissao_venda = models.ForeignKey(Comissao, on_delete=models.DO_NOTHING)
    data_venda = models.DateField(auto_now_add=True)
    valor_venda = models.FloatField()
    descricao_venda = models.CharField(max_length=60)


    @property
    def valor_a_receber(self):
        return self.comissao_venda.porcentagem * self.valor_venda


    def __str__(self):
        return str(self.vendedor)

我的问题是当我尝试删除 Comissao 对象时,我收到了这个错误:

FOREIGN KEY constraint failed

我已经被这个错误困了几个小时,希望有人能帮助我...XD

【问题讨论】:

  • 这是由于 DO_NOTHING: ForeignKeys 在数据库级别强制执行:这意味着 commissao_venda 需要引用有效的 Comissao,但如果您删除Commisao,则不再是这种情况,因此数据库拒绝此。
  • 那我该怎么办我已经尝试使用models.SET_DEFAULT 并在porcentagem 字段中设置默认值0,但我也收到此错误:sales.Venda.comissao_venda: (fields.E321) Field specifies on_delete=SET_DEFAULT, but has no default value. HINT: Set a default value, or change the on_delete rule.
  • 正如错误所说,您需要设置一个默认值。你是如何设置默认值的?
  • 这是我在ForeignKey 中所做的,但我仍然收到错误消息...:comissao_venda = models.ForeignKey(Comissao, on_delete=models.SET_DEFAULT, default=0)
  • 您可能应该首先设置default=0,然后迁移,然后将on_delete=设置为SET_DEFAULT

标签: django model foreign-keys


【解决方案1】:

这是由于DO_NOTHINGForeignKeys 在数据库级别强制执行:这意味着commissao_venda 需要引用有效的Comissao,但如果删除Commisao,则情况不再如此,因此数据库拒绝了这一点。或者,如文档所述:

不采取任何行动。如果您的数据库后端强制引用完整性,这将导致IntegrityError,除非您手动将 SQL ON DELETE 约束添加到数据库字段。

通常DO_NOTHING 无论如何都不是一个好主意。问题是你想用Venda 做什么,以防它所指的Comissao 被删除?两个流行的选项是:

  1. CASCADE,在这种情况下,引用 ComissaoVenda(s) 也会被删除。这可能会触发其他删除,因此单个Comissao 最终会触发从多个表中删除大量记录;或

  2. SET_NULL,您必须通过设置null=True [Django-doc] 使您的字段为空。在这种情况下,commissao_venda 将设置为 NULL/None。因此,该字段如下所示:

    comissao_venda = models.ForeignKey(Comissao<b>, null=True</b>, on_delete=models.<b>SET_NULL</b>)

其他选项为PROTECTRESTRICTSET_DEFAULTSET(…)。当然,这完全取决于在这种情况下想要发生什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-01
    • 2018-11-06
    • 1970-01-01
    相关资源
    最近更新 更多