python / expert
Snippet
Django REST Framework Nested Serializer Validation with Source Aliases
Nested serializers in Django REST Framework enable complex object structures to be validated and created in a single request. The key challenge is properly validating nested data while maintaining clean separation of concerns. Using separate validation methods for each field and handling the nested structure in create() allows for robust input processing and proper error messages at both the parent and child level.
snippet.py
1
from rest_framework import serializers\nfrom django.contrib.auth import get_user_model\n\nUser = get_user_model()\n\nclass ProfileSerializer(serializers.Serializer):\n website = serializers.URLField(required=False)\n bio = serializers.CharField(max_length=500, required=False)\n\nclass UserRegistrationSerializer(serializers.Serializer):\n email = serializers.EmailField()\n username = serializers.RegexField(\n regex=r'^[a-zA-Z0-9_]+$',\n max_length=20\n )\n password = serializers.CharField(write_only=True, min_length=8)\n profile = ProfileSerializer()\n\n def validate_email(self, value):\n if User.objects.filter(email__iexact=value).exists():\n raise serializers.ValidationError('Email already registered')\n return value.lower()\n\n def validate_username(self, value):\n if User.objects.filter(username__iexact=value).exists():\n raise serializers.ValidationError('Username taken')\n return value.lower()\n\n def create(self, validated_data):\n profile_data = validated_data.pop('profile')\n user = User.objects.create_user(**validated_data)\n user.profile.website = profile_data.get('website', '')\n user.profile.bio = profile_data.get('bio', '')\n user.profile.save()\n return user
django
Breakdown
1
profile = ProfileSerializer()
Declares nested serializer that DRF automatically instantiates and validates, creating hierarchical data structure in API requests
2
def validate_email(self, value):
Custom field-level validator checking database for duplicate emails with case-insensitive query before allowing registration
3
def validate_username(self, value):
Regex validation combined with database uniqueness check ensures username meets format and availability requirements
4
def create(self, validated_data):
Extracts nested profile data from validated payload, creates user first, then populates related profile with nested values