python / expert
Snippet
Django REST Framework Nested Serializer Validation
This expert DRF pattern shows nested serializer validation and creation. The validate() method performs cross-field validation that spans the entire object, enforcing business rules like requiring minimum skills for specific departments. The create() method handles the nested objects by extracting them from validated_data and creating related instances separately, maintaining proper database integrity.
snippet.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from rest_framework import serializersfrom django.contrib.auth import get_user_modelclass SkillSerializer(serializers.ModelSerializer):class Meta:model = Skillfields = ['id', 'name', 'years_experience']class EmployeeSerializer(serializers.ModelSerializer):skills = SkillSerializer(many=True, required=False)supervisor = serializers.PrimaryKeyRelatedField(queryset=get_user_model().objects.all(),required=False,allow_null=True)class Meta:model = Employeefields = ['id', 'name', 'email', 'department', 'skills', 'supervisor']def validate(self, attrs):department = attrs.get('department')skills = attrs.get('skills', [])if department == 'Engineering' and len(skills) < 2:raise serializers.ValidationError({'skills': 'Engineering department requires at least 2 skills.'})return attrsdef create(self, validated_data):skills_data = validated_data.pop('skills', [])employee = Employee.objects.create(**validated_data)for skill_data in skills_data:Skill.objects.create(employee=employee, **skill_data)return employee
django
Breakdown
1
SkillSerializer(many=True, required=False)
Defines a nested serializer for handling multiple skill objects
2
PrimaryKeyRelatedField(queryset=...)
Validates supervisor ID against the User model's queryset
3
def validate(self, attrs):
Object-level validation method that accesses all submitted data
4
raise serializers.ValidationError({...})
Returns validation errors with field names as dictionary keys
5
skills_data = validated_data.pop('skills', [])
Extracts nested data before creating the parent model
6
Skill.objects.create(employee=employee, ...)
Creates related objects with the parent instance reference