我有两个模型,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
)
您遇到的错误表明序列化程序需要
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 方法来处理相关对象的嵌套创建。