首页 > 解决方案 > 重用现有的 Django REST 框架序列化程序

问题描述

我目前正在使用 Django Rest Framework,并且正在寻找一种方法来重用已定义的序列化器中的某些属性。为了解释,我将公开一些涉及的序列化程序:

完成的序列化器:

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)

正如您在上面所注意到的,这些序列化程序几乎相同,但其中一个是对象的简化版本,因为我不想在某些部分检索不必要的信息。这里的问题是,在这种情况下,我们有一个需要维护两次的方法序列化程序。也许将来,我想添加另一个字段,我需要将它添加到两者中。那么,如何实现一个包含所有字段但我可以重用它并从中提取特定字段的基于序列化程序?

我已经想到了这些选项: 1. 使用 Base Serializer 实例:草稿:

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

使用这种方法,我不知道这是一个好主意还是可能

  1. 使用 SerializerField 草稿:
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 实例的属性,因此它失败了,我不知道如何实现这一点。

您对这种情况有何建议?任何意见,将不胜感激。

谢谢!

标签: djangorestdjango-rest-frameworkserialization

解决方案


您可以将简单的子类化并在完整的字段中添加字段。

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 子类中定义的任何属性都将覆盖父属性,因此您必须手动使用父属性。


推荐阅读