在 django 中创建数据库条目时无法传递实例

问题描述 投票:0回答:1

我有两个模型,DocumentData 和 RecurringInvoice,它们彼此之间具有一对一的关系。当我在 RecurringInvoice 表中创建条目时,我想传递 DocumentData 实例,而不是 id。但我收到一条错误消息:

{'document_data': [ErrorDetail(string='Incorrect type. Expected pk value, received DocumentData.', code='incorrect_type')]} 

如果我传递实例的 id,它就会起作用。据我所知,我们可以传入实例或 id 来链接条目。那为什么我通过实例的时候会失败呢?

相关控制器代码:

try:
            # get the document data instance
            doc_data = DocumentData.objects.get(id=docDataID)
        except DocumentData.DoesNotExist:
            return Response({
                "message": "Document data does not exist"
            }, status=status.HTTP_400_BAD_REQUEST)

        invoice_serializer = RecurringInvoiceSerializer(
            data={
                "document_data": doc_data,
                "send_date": request.data["send_date"],
                "recipients": request.data["recipients"],
                "invoice_name": request.data["invoice_name"]
            }
        )

        if not invoice_serializer.is_valid():
            print(invoice_serializer.errors, invoice_serializer._errors)
            return Response({"message": "Failed to save invoice data"}, status=status.HTTP_400_BAD_REQUEST)

        invoice_serializer.save()

循环发票模型:

class RecurringInvoice(models.Model):
    document_data = models.OneToOneField(
        DocumentData, on_delete=models.CASCADE, null=True, blank=True)
    send_date = models.IntegerField(
        default=1,
        validators=[MinValueValidator(1), MaxValueValidator(28)]
    )
    invoice_name = models.CharField(max_length=255)
    recipients = ArrayField(models.CharField(max_length=100))
    is_paused = models.BooleanField(default=False)
    stop_date = models.DateField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self) -> str:
        return f"ID: {self.id}, Name: {self.invoice_name}, Active Till: {self.stop_date}"

    class Meta:
        verbose_name = "Recurring Invoice"
        verbose_name_plural = "Recurring Invoices"

文档数据模型:

class DocumentData(models.Model):
    invoices_sent_count = models.IntegerField(default=0)
    service_category = models.CharField(max_length=255, blank=True, null=True)
    from_company_name = models.CharField(max_length=255)
    from_company_number = models.CharField(
        max_length=255, blank=True, null=True
    )
    from_company_address = models.CharField(
        max_length=255, blank=True, null=True
    )
django django-models one-to-one
1个回答
0
投票

您遇到的错误表明序列化程序需要

DocumentData
实例的主键 (pk) 值,而不是实例本身。这是因为在创建或更新相关对象时,Django REST Framework 序列化程序默认期望关系的主键。

要直接传递实例而不是主键,您需要修改序列化器以正确接受和处理嵌套关系。您可以通过使用嵌套序列化器来实现这一点。以下是修改序列化器的方法:

from rest_framework import serializers

class DocumentDataSerializer(serializers.ModelSerializer):
    class Meta:
        model = DocumentData
        fields = ['id', 'invoices_sent_count', 'service_category', 'from_company_name', 'from_company_number', 'from_company_address']

class RecurringInvoiceSerializer(serializers.ModelSerializer):
    document_data = DocumentDataSerializer()

    class Meta:
        model = RecurringInvoice
        fields = ['document_data', 'send_date', 'recipients', 'invoice_name']

    def create(self, validated_data):
        document_data_data = validated_data.pop('document_data')
        document_data = DocumentData.objects.create(**document_data_data)
        recurring_invoice = RecurringInvoice.objects.create(document_data=document_data, **validated_data)
        return recurring_invoice

当您将

document_data
实例传递给
RecurringInvoiceSerializer
时,它将自动处理创建相关的
DocumentData
实例。重写序列化器中的 create 方法来处理相关对象的嵌套创建。

© www.soinside.com 2019 - 2024. All rights reserved.