Django-rest-framework: Serializer mixin fields not getting picked up

Created on 12 Sep 2016  路  9Comments  路  Source: encode/django-rest-framework

I would like to declare som common fields in a mixin class, used by subclasses of both serializer.Serializer and serializer.ModelSerializer. These fields, however, seems not to be picked up, even though defined in Meta.fields. Is this by design?

Repro:

class TestSerializerMixin:
    def test_mixin(self):
        class MyMixin(object):
            some_field = serializers.BooleanField()

        class MySerializer(MyMixin, serializers.Serializer):
            class Meta:
                fields = ['some_field']

        serializer = MySerializer(data={})
        serializer.is_valid()
        assert 'some_field' in serializer.errors

=>

    assert 'some_field' in serializer.errors
E   assert 'some_field' in {}
E    +  where {} = MySerializer(data={}):.errors

Most helpful comment

The metaclass is considered as internal since it's not documented. However, it's unlikely to change.

All 9 comments

Fields are gathered on classes that inherit from serializers.
Your mixin has object as parent and thus break the field introspection.

Ok, see _declared_fields is populated in SerializerMetaclass. Would it be ok to use this class on the mixin to get the fields registered?

Should likely do the trick

It does:

class TestSerializerMixin:
    def test_mixin(self):
        @six.add_metaclass(serializers.SerializerMetaclass)
        class MyMixin(object):
            some_field = serializers.BooleanField()

        class MySerializer(MyMixin, serializers.Serializer):
            class Meta:
                fields = ['some_field2']

        serializer = MySerializer(data={})
        serializer.is_valid()
        assert 'some_field' in serializer.errors

I more asking if this from a framework design perspective is ok or if the meta class is considered internal.

The metaclass is considered as internal since it's not documented. However, it's unlikely to change.

Why do

@six.add_metaclass(serializers.SerializerMetaclass)
class MyMixin(object):

when you can just do

class MyMixin(serializers.Serializer):

especially since the former is not technically a public API? Is there something I'm missing? ModelSerializer inherits from Serializer.

I'm using this for both Serializer and ModelSerializer. Not sure about the consequences for multiple inheritance like that. Guess it should work if the mixin class is listed after the ModelSerializer

Using Serializer instead of just the meta may mess with heritage if some intermediate mixins do override some members.

I know one thing that could be problematic when inheriting serializers.Serializer is having to add definitions for all abstract methods of Serializer in said mixin. I used the metaclass and was successful in achieving what I wanted.

Was this page helpful?
0 / 5 - 0 ratings