-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDRF_Serializer.py
130 lines (91 loc) · 5.12 KB
/
DRF_Serializer.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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
## Serilizer:
Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON,
XML or other content types. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the
incoming data.
The serializers in REST framework work very similarly to Django's Form and ModelForm classes. We provide a Serializer class which gives you a powerful,
generic way to control the output of your responses, as well as a ModelSerializer class which provides a useful shortcut for creating serializers that deal
with model instances and querysets.
## Validation
1. Field-level validation
You can specify custom field-level validation by adding .validate_<field_name> methods to your Serializer subclass. These are similar to the .clean_<field_name> methods on
Django forms.
return: Your validate_<field_name> methods should return the validated value or raise a serializers.ValidationError
Example:
from rest_framework import serializers
class BlogPostSerializer(serializers.Serializer):
title = serializers.CharField(max_length=100)
content = serializers.CharField()
def validate_title(self, value):
"""
Check that the blog post is about Django.
"""
if 'django' not in value.lower():
raise serializers.ValidationError("Blog post is not about Django")
return value
Note: If your <field_name> is declared on your serializer with the parameter required=False then this validation step will not take place if the field is not included.
2. Object-level validation
To do any other validation that requires access to multiple fields, add a method called .validate() to your Serializer subclass. This method takes a single argument,
which is a dictionary of field values. It should raise a serializers.ValidationError if necessary, or just return the validated values.
from rest_framework import serializers
class EventSerializer(serializers.Serializer):
description = serializers.CharField(max_length=100)
start = serializers.DateTimeField()
finish = serializers.DateTimeField()
def validate(self, data):
"""
Check that start is before finish.
"""
if data['start'] > data['finish']:
raise serializers.ValidationError("finish must occur after start")
return data
3. Validators
Individual fields on a serializer can include validators, by declaring them on the field instance, for example:
def multiple_of_ten(value):
if value % 10 != 0:
raise serializers.ValidationError('Not a multiple of ten')
class GameRecord(serializers.Serializer):
score = IntegerField(validators=[multiple_of_ten])
## Partial updates
By default, serializers must be passed values for all required fields or they will raise validation errors. You can use the partial argument in
order to allow partial updates.
# Update `comment` with partial data
serializer = CommentSerializer(comment, data={'content': 'foo bar'}, partial=True)
## Dealing with nested objects
class UserSerializer(serializers.Serializer):
email = serializers.EmailField()
username = serializers.CharField(max_length=100)
class CommentSerializer(serializers.Serializer):
user = UserSerializer()
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
Note: If a nested representation may optionally accept the None value you should pass the required=False flag to the nested serializer.
class CommentSerializer(serializers.Serializer):
user = UserSerializer(required=False) # May be an anonymous user.
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
Note: Similarly if a nested representation should be a list of items, you should pass the many=True flag to the nested serializer.
class CommentSerializer(serializers.Serializer):
user = UserSerializer(required=False)
edits = EditItemSerializer(many=True) # A nested list of 'edit' items.
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
## Writing .create() methods for nested representations
If you're supporting writable nested representations you'll need to write .create() or .update() methods that handle saving multiple objects.
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer()
class Meta:
model = User
fields = ['username', 'email', 'profile']
def create(self, validated_data):
profile_data = validated_data.pop('profile')
user = User.objects.create(**validated_data)
Profile.objects.create(user=user, **profile_data)
return user
## ModelSerializer
The ModelSerializer class provides a shortcut that lets you automatically create a Serializer class with fields that correspond to the Model fields.
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ['id', 'account_name', 'users', 'created']
fields = '__all__' # all fields
exclude = ['users']