Reputation: 561
I need to store bitmap representation of an image in my code, so I did this in my model
logo = models.BinaryField(blank=True, null=True)
now Django-rest doesn't have a serializer field for BinaryField. If I create my own serializer field for this, how would I be able to use it in my code ? For example, if I create something like
class MyBinaryField(serializers.Field):
def to_representation(self, obj):
return base64.b64decode(obj)
def to_internal_value(self, data):
return base64.encodestring(data)
How can I plug this mapping of models.BinaryField and MyBinaryField in my serializer. I know there is a default serializer_field_mapping map available and I can override it, but I want to use existing serializer_field_mapping as well. How can I insert my new entry into existing serializer_field_mapping or declare new values in current map ?
Upvotes: 4
Views: 3872
Reputation: 515
Taking inspiration from @prokher, another way of expanding the serializer_field_mapping
attribute of the ModelSerializer
would be using a mixin. This method has the added benefit of not overwriting the base serializer, and only using the mixin when you have fields that need to be mapped.
One way of defining this mixin would be overwriting the build_standard_field()
method, since this is called in the ModelSerializer
to build the fields that can be mapped from the serializer_field_mapping
. We can simply expand the dict holding the mapping to add the custom fields that aren't currently supported, and then call the original method to actually build the field.
The mixin for a given field serializer MyCustomField
that maps to a Django model field MyModelField
can be defined like so:
from rest_framework import serializers
class MyCustomField(serializers.Field):
pass
class MyCustomFieldMappingMixin:
"""A `ModelSerializer` mixin that extends
the default serializer field mapping
to include `MyCustomField`.
"""
def build_standard_field(self, field_name, model_field):
self.serializer_field_mapping[MyModelField] = MyCustomField
return super().build_standard_field(field_name, model_field)
And then your serializer class can extend from this mixin to add support for MyModelField
like so:
from rest_framework import serializers
# The mixin has to be imported before the ModelSerializer
# otherwise, MyCustomField won't be used to map your field
def MySerializer(
MyCustomFieldMappingMixin,
serializers.ModelSerializer,
):
class Meta:
model = MyModel
fields = ("my_model_field") # this should map to MyCustomField
Upvotes: 0
Reputation: 490
Just make a copy of serializer_field_mapping
from the base class of your serializer and update it with new "model field - serializer" field pair. For example if you use ModelSerializer
subclass then:
from rest_framework import serializers
class MySerializer(serializers.ModelSerializer):
serializer_field_mapping = (
serializers.ModelSerializer.serializer_field_mapping.copy()
)
serializer_field_mapping[models.BinaryField] = MyBinaryField
Upvotes: 4
Reputation: 5879
One way to do this,
class MySerializer(serializers.Serializer):
logo = MyBinaryField()
However, I suppose you are asking about overriding model serializer field then you could use the following,
class AccountSerializer(serializers.ModelSerializer):
logo = MyBinaryField(read_only=True)
class Meta:
model = Account
Upvotes: 0