Django REST Framework外键序列化后Angular2 POST请求报500错误
Hey there! Let's tackle your two related issues head-on—they both stem from how you're handling foreign key fields in your ProductSerializer, so we'll fix them together.
What's Causing the Problem?
When you added:
category = serializers.CharField(source='category.category', read_only=True) type_units = serializers.CharField(source='type_units.type', read_only=True)
you turned your model's foreign key fields into read-only display fields. Here's why that breaks POST requests:
- DRF ignores read-only fields during deserialization (processing POST/PUT data), so it can't map your Angular form data to the actual foreign key values needed to create a
Productinstance. - Your
Productmodel almost certainly requires non-null values forcategoryandtype_units—without a way to receive those values from your POST request, Django throws a 500 server error (usually anIntegrityErrorfor missing required fields).
Solution: Separate Display and Input Fields
We need to keep the friendly display names for your frontend, while adding proper writable fields to handle foreign key associations. Here are two clean approaches:
Approach 1: Rename Display Fields + Keep Writable Foreign Keys
This is the most straightforward fix. We'll rename your read-only display fields and add writable PrimaryKeyRelatedField entries for the actual foreign keys:
from rest_framework import serializers from .models import Product, Category, TypeUnits class ProductSerializer(serializers.HyperlinkedModelSerializer): # Read-only fields for frontend display (shows the category/unit name) category_name = serializers.CharField(source='category.category', read_only=True) type_units_name = serializers.CharField(source='type_units.type', read_only=True) # Writable fields for handling foreign key associations (accepts model IDs) category = serializers.PrimaryKeyRelatedField(queryset=Category.objects.all()) type_units = serializers.PrimaryKeyRelatedField(queryset=TypeUnits.objects.all()) class Meta: model = Product # Make sure to include both the writable fields and display fields fields = ( 'id', 'image', 'pro_name', 'description', 'category', 'category_name', 'sales', 'cost', 'tax', 'type_units', 'type_units_name' )
Approach 2: Use SerializerMethodFields for Display
If you prefer not to rename fields, you can use SerializerMethodField to generate display names while keeping the original foreign key fields writable:
class ProductSerializer(serializers.HyperlinkedModelSerializer): # Writable foreign key fields category = serializers.PrimaryKeyRelatedField(queryset=Category.objects.all()) type_units = serializers.PrimaryKeyRelatedField(queryset=TypeUnits.objects.all()) # Custom methods to return display names def get_category_name(self, obj): return obj.category.category def get_type_units_name(self, obj): return obj.type_units.type class Meta: model = Product fields = ( 'id', 'image', 'pro_name', 'description', 'category', 'category_name', 'sales', 'cost', 'tax', 'type_units', 'type_units_name' )
Angular Frontend Adjustment
Make sure your Angular POST request sends the ID values of the selected category and unit type, not the display names. For example, your request body should look like this:
{ "pro_name": "Wireless Headphones", "description": "Noise-cancelling over-ear headphones", "category": 3, // ID of the "Electronics" category "type_units": 1, // ID of the "Piece" unit type "sales": 299.99, "cost": 150.00, "tax": 0.08 }
In your Angular dropdowns, set the option value to the category/unit ID, and the display text to the name.
Quick Fix for Syntax Error
Also, notice you have tax... in your fields list—make sure to replace that with the actual field name (like tax) to avoid additional serialization errors.
内容的提问来源于stack exchange,提问作者Sudharsan Venkatraj

