22👍
You can customize data in your CommentSerializer.validate_content
method:
This is your serializer:
class CommentSerializer(serializers.Serializer):
email=serializers.EmailField()
content=serializers.CharField()
def validate_content(self,value):
#If content is 'baz' returns 'foo'
if value and value == "baz":
return "foo"
return value
Let’s try with wrong values (for email):
>>> serializer = CommentSerializer(data={'email': 'foobar', 'content': 'baz'})
>>> serializer.data
Traceback (most recent call last):
raise AssertionError(msg)
AssertionError: When a serializer is passed a `data` keyword argument
you must call `.is_valid()` before attempting to access the
serialized `.data` representation.
You should either call .is_valid()
first, or access .initial_data
instead.
>>> serializer.initial_data
{'content': 'baz', 'email': 'foobar'}
>>> serializer.validated_data
Traceback (most recent call last):
raise AssertionError(msg)
AssertionError: You must call `.is_valid()` before accessing `.validated_data`.
>>> serializer.is_valid()
False
>>> serializer.data
{'content': 'baz', 'email': 'foobar'}
>>> serializer.validated_data
{}
>>> serializer.errors
{'email': [u'Enter a valid email address.']}
Now Let’s try with correct values
>>> serializer2 = CommentSerializer(data={'email': 'foobar@email.it',
'content': 'baz'})
>>> serializer2.is_valid()
True
>>> serializer2.initial_data
{'content': 'baz', 'email': 'foobar@email.it'}
>>> serializer2.errors
{}
>>> serializer2.data
{'content': u'foo', 'email': u'foobar@email.it'}
>>> serializer2.validated_data
OrderedDict([(u'email', u'foobar@email.it'), (u'content', u'foo')])
So:
data
: is a dict and you can see it only afteris_valid()
(you can see only not validated values)validated_data
is anOrderedDict
and you can see it only afteris_valid()
andis_valid() == True
16👍
data
and validated_data
will not always be the same.
For example:
class UserSerializer(serializers.Serializer):
name = serializers.CharField()
phone = serializers.CharField(required=False, allow_null=True)
We could get different data:
>>> user = UserSerializer(data={'name': 'Foo'})
>>> user.is_valid()
True
>>> user.data
{'name': 'Foo', 'phone': None}
>>> user.validated_data
{'name': 'Foo'}
Based on BaseSerializer
internal code, data
property is just self.to_representation(self.validated_data)
whenever the serializer has been validated:
elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
self._data = self.to_representation(self.validated_data)
And in this case to_representation
internal code sets to None
those cases.
Because of this behaviour I would recommend using validated_data
over data
. If you used data
with a serializer like this, and explicitly sets attributes to an object based on data
, you could set to None
attributes that did not exist in initial data.
- [Django]-What is the path that Django uses for locating and loading templates?
- [Django]-Django – Overriding the Model.create() method?
- [Django]-Docker/Kubernetes + Gunicorn/Celery – Multiple Workers vs Replicas?
11👍
DESERIALIZING
Data is the input to a Serializer
eg
serializer = CommentSerializer(data={'email': 'foobar', 'content': 'baz'})
As you can see email is invalid, so the following rule apply(from official docmentation)
When deserializing data, you always need to call is_valid() before
attempting to access the validated data, or save an object instance
serializer.is_valid()
If the data
your trying to deserialize is valid #True
then you can access the validated data as
serializer.validated_data
ADDITION
There is no data transformation after validation, it only check if your data is valid, if any validation errors occur, the .errors
property will contain a dictionary representing the resulting error messages.
A good example is when your doing field validation
class CommentSerializer(serializers.Serializer):
title = serializers.CharField(max_length=100)
def validate_title(self, value):
if 'django' not in value.lower():
raise serializers.ValidationError("Title is not about Django")
return value
validate_title
will called each time you call .is_valid()
, as you can see it only check if the title is django related, if True
the value which in this case title is returned else ValidationError
is raised. NO CHANGE OF DATA HERE
- [Django]-How to dynamically compose an OR query filter in Django?
- [Django]-Raw SQL queries in Django views
- [Django]-Django – FileField check if None