【问题标题】:IntegrityError: null value in column "invoiceOwner_id" violates not-null constraintIntegrityError:“invoiceOwner_id”列中的空值违反非空约束
【发布时间】:2020-08-05 01:28:47
【问题描述】:

在我的 django 应用程序中,每当我想添加一个使用表 paymentInvoice 的新对象时,我都会遇到困难。

我从我的 api 得到的错误看起来像这样

/api/clients/invoice/ 处的 IntegrityError “invoiceOwner_id”列中的空值违反非空约束 详细信息:失败行包含 (10, INV-0006, Lix, 2020-08-04, 1, Pending, 3000, null)。

注意:我还没有创建字段invoiceOwner_id,postgres 自动添加了它,或者更确切地说是使用它作为我的invoiceOwner 字段的表示

class Purchaser(models.Model):
    name = models.CharField(max_length=50)
    phone = models.CharField(max_length=20, unique=True)
    email = models.EmailField(max_length=255, unique=True, blank=True)
    image = models.ImageField(default='default.png', upload_to='customer_photos/%Y/%m/%d/')
    data_added = models.DateField(default=datetime.date.today)

    def __str__(self):
        return self.name


class paymentInvoice(models.Model):

    invoiceNo = models.CharField(max_length=50, unique=True, default=increment_invoice_number)
    invoiceOwner = models.ForeignKey(Purchaser, on_delete=models.CASCADE, related_name="invoice_detail")
    product = models.CharField(max_length=50, blank=True)
    date = models.DateField(default=datetime.date.today)
    quantity = models.PositiveSmallIntegerField(blank=True, default=1)
    payment_made = models.IntegerField(default=0)

    def __str__(self):
        return self.invoiceOwner.name

序列化程序文件

class paymentInvoiceSerializer(serializers.ModelSerializer):
    invoiceOwner = serializers.SerializerMethodField()

    class Meta:
        model = paymentInvoice
        fields = '__all__'

    def get_invoiceOwner(self, instance):
        return instance.invoiceOwner.name

视图文件

class paymentInvoiceListCreateView(ListCreateAPIView):

    serializer_class = paymentInvoiceSerializer
    queryset = paymentInvoice.objects.all().order_by('-date')

GET api 调用的结果。

{
    "id": 1,
    "invoiceOwner": "Martin",
    "invoiceNo": "INV-0001",
     "product": "",
    "date": "2020-08-04",
    "quantity": 1,
    "payment_made": 0
}

尝试以POST 的身份在下方传递,但出现主要错误

{
    "invoiceOwner": "Becky",
    "product": "Lix",
    "quantity": 1,
    "payment_made": 3000
}

【问题讨论】:

  • 您需要在序列化程序中显式覆盖create 方法,因为您的模型作为外键invoiceOwner,只是为了首先将该实例创建为Purchaser 实例
  • 我试过但卡住了。我将如何去做。使用提供的代码

标签: django api django-models django-rest-framework django-serializer


【解决方案1】:

您的 serializers.py 中的“invoiceOwner”是一个 SerializerMethodField,它是 readonly 这就是你得到错误的原因,你必须自己定义 create 方法

【讨论】:

  • 请使用上述代码协助 create 方法
【解决方案2】:

正如我在评论中所说:您需要在序列化程序中显式覆盖 create 方法,因为您的模型具有外键 invoiceOwner,只是为了首先将该实例创建为 Purchaser 实例。

你可以试试下面的代码:

class paymentInvoiceSerializer(serializers.ModelSerializer):
    invoiceOwner = serializers.SerializerMethodField()

    class Meta:
        model = paymentInvoice
        fields = '__all__'

    def get_invoiceOwner(self, instance):
        return instance.invoiceOwner.name

   def create(self, validated_data):
        purchaser_name = validated_data.get("invoiceOwner") 
        purchaser = Purchaser(name=purchaser_name,
            # you need to have phone, email, since these fields are unique,
            # they can't remain null
        )
        purchaser.save()
        return paymentInvoice.objects.create(invoiceOwner = purchaser, **validated_data)

【讨论】:

  • null=True, blank=True 可以为空,但您的代码中的问题是 unique=True 将导致至少 2 个具有空值的实例出现问题... 2 个具有空值的实例相同的字段不是唯一的
  • 我已经删除了唯一属性并添加了blank=True,但是当我在添加你的函数后尝试创建新对象时,我收到一个错误ValueError at /api/clients/invoice/ save() prohibited to prevent data loss due to unsaved related object 'invoiceOwner'.
  • 表示已经使用的实例,不保存。我怀疑你没有保存购买者,我更新了我的答案
  • 不好意思,根据您发布的数据,您的字段名称不是name,而是:invoiceOwner。例如:"invoiceOwner": "Becky",。答案已更新
  • 正如我在答案中所说,您是否将null=True 添加到将保持为空甚至为空的2个字段中? phone = models.CharField(max_length=20, blank=True, null=True) 也适用于手机
猜你喜欢
  • 2013-05-12
  • 1970-01-01
  • 2016-10-21
  • 2016-01-18
  • 2020-08-20
  • 2019-04-08
  • 2017-10-15
  • 1970-01-01
  • 2021-01-21
相关资源
最近更新 更多