我目前正在使用Django Rest Framework,我正在寻找一种方法来重用已经定义好的Serializer的一些属性。为了解释,我将公开一些相关的序列化器。
完成的序列化器:
class ProductSerializer(serializers.ModelSerializer):
subscribed = serializers.SerializerMethodField()
other_field = serializers.SerializerMethodField()
class Meta:
model = Product
fields = [
'id',
'name',
'subscribed',
'other_field',
'x',
'y',
'z'
]
def get_subscribed(self, product: Product):
return product.is_user_subscribed(self.context['request'].user)
简化的序列化器。
class ProductSimplifiedSerializer(serializers.ModelSerializer):
subscribed = serializers.SerializerMethodField()
class Meta:
model = Product
fields = [
'id',
'name',
'subscribed'
]
def get_subscribed(self, product: Product):
return product.is_user_subscribed(self.context['request'].user)
正如你可以注意到上面,这些序列化器几乎是一样的,但其中一个是对象的简化版本,因为我不想在某些部分检索不必要的信息。这里的问题是,在这种情况下,我们有一个方法序列化器,需要维护两次。也许在未来,我还想添加另一个字段,我需要把它添加到两个字段中。那么,如何实现一个Based Serializer,其中所有的字段都被包含在内,但我可以重用它并从中提取特定的字段?
我已经想好了这些方案:1.使用Base Serializer instance:Draft。
def to_representation(self, instance)
desired_format = self.context['format']
if desired_format == 'simplified':
fields = ['fields_for_simplified']
elif desired_format == 'regular':
fields = ['fields_for_regular']
for field in fields:
# make the representation
用这种方法,我不知道是否是个好主意,或者说是否可行
class UserSubscribed(serializer.SerializerField)
def to_representation(self, instance):
return 'representation'
class ProductSimplifiedSerializer(serializers.ModelSerializer):
user_subscribed = UserSubscribed()
class Meta:
model = Product
fields = [
'id',
'name',
'user_subscribed'
]
我觉得最后一个比较好,问题是这个_user_subscribed_不是Product实例的属性,因此失败了,我不知道如何实现。
对于这种情况,您有什么建议?任何建议都将被感激。
谢谢!我目前使用的是Django Restrection。
你可以子类简单的一个和添加字段在完整的一个。
class ProductSimplifiedSerializer(serializers.ModelSerializer):
subscribed = serializers.SerializerMethodField()
class Meta:
model = Product
fields = [
'id',
'name',
'subscribed'
]
def get_subscribed(self, product: Product):
return product.is_user_subscribed(self.context['request'].user)
class ProductSerializer(ProductSimplifiedSerializer):
other_field = serializers.SerializerMethodField()
class Meta(ProductSimplifiedSerializer.Meta):
fields = ProductSimplifiedSerializer.Meta.fields + [
'other_field',
'x',
'y',
'z'
]
这里的技巧是,你可以子类的 Meta
类的属性。你在Meta子类中定义的任何属性都会覆盖父类的属性,所以你必须手动使用父类的属性。
你可以为序列化器类创建mixin,它可以让你指定哪些字段将在序列化器中被 "使用",其他的将被忽略。
class DynamicFieldsMixin(object):
def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
fields = kwargs.pop('fields', None)
# Instantiate the superclass normally
super().__init__(*args, **kwargs)
if fields is not None:
# Drop any fields that are not specified in the `fields` argument.
allowed = set(fields)
existing = set(self.fields)
for field_name in existing - allowed:
self.fields.pop(field_name)
然后你可以像这样使用你的序列器。
class ProductSerializer(DynamicFieldsMixin, serializers.ModelSerializer)
serializer = ProductSerializer(fields=("id", "name", "subscribed"))