with instalar framework espaƱol coreapi python django django-rest-framework abstract-class

python - instalar - django rest framework serie de clases abstractas



django rest swagger (3)

Creo que el siguiente enfoque es más limpio. Puede establecer el campo "abstracto" en true para el serializador base y agregar su lógica común para todos los serializadores secundarios.

class TypeBaseSerializer(serializers.Serializer): class Meta: model = TypeBase fields = (''id'', ''name'') abstract = True def func(...): # ... some logic

Y luego cree serializadores secundarios y úselos para la manipulación de datos.

class PersonTypeSerializer(TypeBaseSerializer): class Meta: model = PersonType fields = (''id'', ''name'') class CompanyTypeSerializer(TypeBaseSerializer): class Meta: model = CompanyType fields = (''id'', ''name'')

Ahora puede usar los dos serializadores normalmente para cada modelo.

Pero si realmente desea tener un serializador para ambos modelos, cree un modelo de contenedor y un serializador para él también. Eso es mucho más limpio :)

Tengo algunos modelos como estos:

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

Teniendo esto, quiero crear solo un serializador que contenga todos estos tipos de campo (serialización, deserialización, actualización y guardado).

Para ser más específico, solo quiero un serializador (TypeBaseSerializer) que imprima el menú desplegable en la interfaz de usuario, serialice la respuesta json, deserialícela en la publicación y guárdela para todos mis tipos basados.

Algo como esto:

class TypeBaseSerializer(serializers.Serializer): class Meta: model = TypeBase fields = (''id'', ''name'')

¿Es posible?


No puede usar un ModelSerializer con un modelo base abstracto. Desde restframework.serializers:

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

Escribí una función serializer_factory para un problema similar:

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

Luego puede usar la fábrica para producir serializadores según sea necesario:

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

Ahora instanciar diferentes serializadores de subclase:

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


Simplemente iterando un poco sobre la respuesta de @ adki:

  1. es posible omitir el modelo para TypeBaseSerializer;
  2. Los serializadores derivados pueden hacer referencia a TypeBaseSerializer.meta.fields, por lo que los cambiaría en un solo lugar.

class TypeBaseSerializer(serializers.Serializer): class Meta: fields = (''id'', ''name'', ''created'') abstract = True def func(...): # ... some logic class PersonTypeSerializer(TypeBaseSerializer): class Meta: model = PersonType fields = TypeBaseSerializer.meta.fields + (''age'', ''date_of_birth'') class CompanyTypeSerializer(TypeBaseSerializer): class Meta: model = CompanyType fields = TypeBaseSerializer.meta.fields