I have a quick question about overriding is_valid
. Self is a rest_framework.serializers.ModelSerializer
. I'm trying to figure out if there is a better way to modify internal data than reading/writing to the data._kwargs
property. I know I can get the data pre-validation via a self.get_initial()
call. But I'd also like to be able to write data. The purpose here is to change Image Data, if not properly formatted, into a format our models accept so that our API is more flexible. I know there may be other ways to accomplish my goals, but my generic question is
Is there a good method to set data on a serializer before is_valid() is called?
because it applies to other cases too. Thank you!
def is_valid(self, raise_exception=True):
imageHandler = ImageHandler()
if "member_profile" in self._kwargs["data"]:
if "profile_image" in self._kwargs["data"]["member_profile"]:
self._kwargs["data"]["member_profile"]["profile_image"] = imageHandler.convertImage(
self._kwargs["data"]["member_profile"]["profile_image"])
else:
self._kwargs["data"]["member_profile"] = {}
valid = super(AuthUserModelSerializer, self).is_valid(raise_exception=raise_exception)
return valid
is_valid perform validation of input data and confirm that this data contain all required fields and all fields have correct types. If validation process succeded is_valid set validated_data dictionary which is used for creation or updating data in DB.
Serializers in Django REST Framework are responsible for converting objects into data types understandable by javascript and front-end frameworks. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.
To serialize a queryset or list of objects instead of a single object instance, you should pass the many=True flag when instantiating the serializer. You can then pass a queryset or list of objects to be serialized.
The ModelSerializer class is the same as a regular Serializer class, except that: It will automatically generate a set of fields for you, based on the model. It will automatically generate validators for the serializer, such as unique_together validators. It includes simple default implementations of .
Personally, I would write a custom field for the profile_image(or extend image field) and overwrite the to_internal_value method to hold this custom logic. This will be called by during field validation. Here is a psuedo-example:
class ProfileImageField(ImageField):
def to_internal_value(self, data):
converted = ImageHandler().convertImage(data)
return super(ProfileImageField,self).to_internal_value(converted)
To answer your generic question, I usually use custom to_internal_value() methods for fields and serializers to handle any discrepancies between incoming and expected data. These methods are run during validation and allow you to control the data in an obvious manner to someone reading your code in the future.
Clarification
The serializer itself has a 'to_interval_value' method which allows you to modify/process the data you pass to it during the serializer's data validation (but before the data itself is validated). Modifying data at this point will also happen before field level validation. So, if you want to rename a field that is being passed to your endpoint into something you expect, or if you want to add a null value for a field that has not been passed in the data, this would be the place to do it.
class MySerializer(serializers.ModelSerializer):
def to_internal_value(self, data):
if 'member_profile' not in data:
data['member_profile'] = {}
return super(MySerializer,self).to_internal_value(data)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With