Django的REST框架抽象类串行
我有一些车型,如这些:Django的REST框架抽象类串行
class TypeBase(models.Model):
name = models.CharField(max_length=20)
class Meta:
abstract=True
class PersonType(TypeBase):
pass
class CompanyType(TypeBase):
pass
到这一点,我想只创建一个串行包含所有这些字段类型(序列化,反序列化,更新和保存)。更具体地说,我只需要一个在UI上打印Dropdown的序列化程序(TypeBaseSerializer),序列化json响应,在后期将其反序列化并将其保存为所有基于我的类型。
事情是这样的:
class TypeBaseSerializer(serializers.Serializer):
class Meta:
model = TypeBase
fields = ('id', 'name')
这可能吗?
你can't use a ModelSerializer
与抽象的基本模型。 从restframework.serializers:
if model_meta.is_abstract_model(self.Meta.model):
raise ValueError(
'Cannot use ModelSerializer with Abstract Models.'
)
我写了一个serializer_factory功能类似的问题:
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
然后,您可以使用工厂生产串行需要:
def typebase_serializer_factory(mdl):
myserializer = serializer_factory(
mdl,fields=["id","name"],
#owner=HiddenField(default=CurrentUserDefault()),#Optional additional configuration for subclasses
)
return myserializer
现在instanciate不同的子类序列化程序:
persontypeserializer = typebase_serializer_factory(PersonType)
companytypeserializer = typebase_serializer_factory(CompanyType)
该解决方案似乎为我的问题的工作,但有没有办法减少通用性?我认为在我的情况下,我会一直知道我的类型的领域,我只需要动态地实例化它。 –
您可以为子类创建两个序列化器。我处于有7个子类和不同串行器模式的情况,所以通用性至关重要。 –
我认为以下方法更清洁。您可以将基本序列化器的“abstract”字段设置为true,并为所有子序列化器添加公共逻辑。
class TypeBaseSerializer(serializers.Serializer):
class Meta:
model = TypeBase
fields = ('id', 'name')
abstract = True
def func(...):
# ... some logic
然后创建子序列化器并将它们用于数据操作。
class PersonTypeSerializer(TypeBaseSerializer):
class Meta:
model = PersonType
fields = ('id', 'name')
class CompanyTypeSerializer(TypeBaseSerializer):
class Meta:
model = CompanyType
fields = ('id', 'name')
现在你可以使用这两种串行器通常为每个模型。
但是,如果你真的想为两个模型都有一个序列化器,那么也为他创建一个容器模型和一个序列化器。这是干净多了:)
只是迭代有点过@ adki的回答是:
- 有可能跳过型号为TypeBaseSerializer;
- 派生序列化器可以引用TypeBaseSerializer.meta.fields,所以你可以在一个地方改变它们。
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
这个讨论也子类串行有用:https://github.com/tomchristie/django-rest-framework/issues/1926 – PhoebeB