Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BitField serialization using Django REST Framework

I have a model that contains a BitField. When trying to serialize an object using Django Rest Framework, the following error is returned:

{"flags": ["Enter a whole number."]}

(flags is a BitField)

How can I serialize a BitField using Django Rest Framework?

like image 410
Tzach Avatar asked Dec 07 '14 11:12

Tzach


3 Answers

looks like the form of Tzach's answer in rest-framework 3.1 is now

class BitFieldSerializer(serializers.Field):

     def to_internal_value(self, obj):
         return int(obj)

e.g. per http://www.django-rest-framework.org/api-guide/fields/#custom-fields

"Note that the WritableField class that was present in version 2.x no longer exists. You should subclass Field and override to_internal_value() if the field supports data input."

like image 50
David Lam Avatar answered Oct 06 '22 05:10

David Lam


Found the answer. I needed to create a custom serializer for the BitField:

class BitFieldSerializer(serializers.WritableField):        
    def to_native(self, obj):
        return int(obj)

And use it in the model serializer:

class MyModelSerializer(serializers.ModelSerializer):
    flags = BitFieldSerializer()
like image 34
Tzach Avatar answered Oct 06 '22 07:10

Tzach


Here's another option if you want to read and write the flags in a list.

class BitFieldSerializer(serializers.Field):
    def to_internal_value(self, data):
        model_field = getattr(self.root.Meta.model, self.source)
        result = BitHandler(0, model_field.keys())
        for k in data:
            try:
                setattr(result, str(k), True)
            except AttributeError:
                raise serializers.ValidationError("Unknown choice: %r" % (k,))
        return result

    def to_representation(self, value):
        return [i[0] for i in value.items() if i[1] is True]

Example return: ['flag1', 'flag4']

This assumes you are using a ModelSerializer. The way I get the model field's keys (it's flags) seems a little sketchy if anyone knows a better way please comment.

like image 42
Bufke Avatar answered Oct 06 '22 05:10

Bufke