Django Rest Framework发票生成API中invoice.is_valid()验证失败问题求助
invoice.is_valid() Validation Error in Your DRF Invoice API Hey there! Let's break down why your validation is failing and fix it step by step. Looking at your code, error trace, and request data, there are a few key mismatches and missing configurations causing the issue:
1. Mismatched Serializer Field Name
Your InvoiceSerializer defines a field called item = ItemSerializer(many=True), but your request data uses items (plural), and Django's default reverse relation between Invoice and Item is also named items (since Item has a foreign key to Invoice).
DRF is looking for a required item field that doesn't exist in your request, hence the "This field is required" error.
2. Unnecessary Required invoice Field in ItemSerializer
Looking at the traceback, your ItemSerializer automatically includes the invoice foreign key field as a required PrimaryKeyRelatedField. But you don't want the frontend to send this value—you'll associate items with the invoice in your create method. This adds another layer of validation failure because the request doesn't include this field.
3. Inconsistent Key Name in create Method
Your create method tries to pop items from validated data, but before fixing the serializer field name, this key wouldn't exist (since the serializer was looking for item instead).
Fixed Serializers Code
Here's the corrected serializers.py with all these issues addressed:
from django.db.models import fields from rest_framework import serializers from rest_framework.fields import ReadOnlyField from invoiceAPI.models import Seller, Buyer, Invoice, Item class SellerSerializer(serializers.ModelSerializer): id = serializers.IntegerField(read_only=True) class Meta: model = Seller fields = '__all__' class BuyerSerializer(serializers.ModelSerializer): id = serializers.IntegerField(read_only=True) class Meta: model = Buyer fields = '__all__' class ItemSerializer(serializers.ModelSerializer): id = serializers.IntegerField(read_only=True) # Mark the invoice field as read-only so it's not required in the request invoice = serializers.PrimaryKeyRelatedField(read_only=True) class Meta: model = Item fields = '__all__' class InvoiceSerializer(serializers.ModelSerializer): seller = SellerSerializer(many=False) buyer = BuyerSerializer(many=False) # Rename to `items` to match request data and Django's reverse relation items = ItemSerializer(many=True) class Meta: model = Invoice depth = 1 fields = ('seller', 'buyer', 'items', 'date') def create(self, validated_data): seller_data = validated_data.pop('seller') buyer_data = validated_data.pop('buyer') # Now `items` matches the serializer field name items_data = validated_data.pop('items') seller = Seller.objects.create(**seller_data) buyer = Buyer.objects.create(**buyer_data) invoice = Invoice.objects.create(seller=seller, buyer=buyer, **validated_data) # Create each item and associate it with the new invoice for item_data in items_data: Item.objects.create(invoice=invoice, **item_data) return invoice
Bonus: Fix a Minor Bug in Invoice Model
While not related to the validation error, your invoice_number method has a type error—you're trying to concatenate a string with an integer (self.id). Update it to:
def invoice_number(self): id_str = str(self.id) if len(id_str) == 1: return f'Invoice00{id_str}' elif len(id_str) == 2: return f'Invoice0{id_str}' else: return f'Invoice{id_str}'
With these changes, your invoice.is_valid() should pass, and the API will correctly create the seller, buyer, invoice, and associated items from your request data.
内容的提问来源于stack exchange,提问作者Akash Saingar

