django rest framework abstract class serializer

后端 未结 4 971
名媛妹妹
名媛妹妹 2021-02-07 05:01

I have some models like these:

class TypeBase(models.Model):
    name = models.CharField(max_length=20)
    class Meta:
        abstract=True

class PersonType(T         


        
4条回答
  •  陌清茗
    陌清茗 (楼主)
    2021-02-07 05:39

    You can't use a ModelSerializer with an abstract base model. From restframework.serializers:

    if model_meta.is_abstract_model(self.Meta.model):
            raise ValueError(
                'Cannot use ModelSerializer with Abstract Models.'
            )
    

    I wrote a serializer_factory function for a similar problem:

    from collections import OrderedDict
    from restframework.serializers import ModelSerializer
    def serializer_factory(mdl, fields=None, **kwargss):
    """ Generalized serializer factory to increase DRYness of code.
    
    :param mdl: The model class that should be instanciated
    :param fields: the fields that should be exclusively present on the serializer
    :param kwargss: optional additional field specifications
    :return: An awesome serializer
    """
    
        def _get_declared_fields(attrs):
            fields = [(field_name, attrs.pop(field_name))
                      for field_name, obj in list(attrs.items())
                      if isinstance(obj, Field)]
            fields.sort(key=lambda x: x[1]._creation_counter)
            return OrderedDict(fields)
    
        # Create an object that will look like a base serializer
        class Base(object):
            pass
    
        Base._declared_fields = _get_declared_fields(kwargss)
    
        class MySerializer(Base, ModelSerializer):
            class Meta:
                model = mdl
    
            if fields:
                setattr(Meta, "fields", fields)
    
        return MySerializer
    

    You can then use the factory to produce serializers as needed:

    def typebase_serializer_factory(mdl):
        myserializer = serializer_factory(
            mdl,fields=["id","name"],
            #owner=HiddenField(default=CurrentUserDefault()),#Optional additional configuration for subclasses 
          )
        return myserializer
    

    Now instanciate different subclass serializers:

    persontypeserializer = typebase_serializer_factory(PersonType)
    companytypeserializer = typebase_serializer_factory(CompanyType)
    

提交回复
热议问题