django-rest-framework动态地将SerializerMethodField添加到Serializer

时间:2014-11-08 16:30:25

标签: python django django-rest-framework

我有很多类似的字段应该以类似的方式创建。

from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    is_friend = serializers.SerializerMethodField('get_is_friend')
    # ...

    def get_is_friend(self, obj):
        user = self.context['request'].user
        return user.id in obj.friend_list
    # ...

    class Meta:
        fields = (
            'is_friend',
            # ...
        )

目前我有一个装饰者,它创造了我所需要的一切,除了创建SerializerMethodField

def additional_fields_decorator(cls):
    relation_methods = (
        {
            'name': 'is_friend',
            'field_name': 'friends',
        },
        # ...
    )

    def relation_method_factory(field_name):
        def wrapper(self, obj):
            user = self.context['request'].user
            return user.id in getattr(obj, field_name)
        return wrapper

    for method in relation_methods:
        name = method['name']
        name_getter = 'get_{0}'.format(name)

        setattr(cls, name_getter, relation_method_factory(method['field_name']))
        cls.Meta.fields += (name,)
        # following line fails
        setattr(cls, name, serializers.SerializerMethodField(name_getter))

    return cls


@additional_fields_decorator
class UserSerializer(serializers.ModelSerializer):
    pass

谁知道为什么无法在Serializer类之外创建SerializerMethodField

2 个答案:

答案 0 :(得分:0)

当DRF处理您的UserSerializer课程时,它会在课程范围内查找SerializerMethodField。因此,当您在类之外声明方法时,它将无法看到它。

答案 1 :(得分:0)

我最近遇到了类似的问题,我认为您可以通过使用内置类型的方法动态创建序列化程序类来动态添加SerializerMethodField。像这样:

def generate_serializer(new_field):
    all_fields = ['field1', 'field2', new_field]

    class Meta:
        model = Model
        fields = all_fields

    def generate_new_field_method(key):
        def get_new_field(self, instance):
            # some logic based on field name
            pass
        return get_new_field

    dct = {
        'new_field': serializers.SerializerMethodField(),
        'get_new_field': generate_new_field_method(new_field),
        'Meta': Meta,
    }

    return type('DynamicSerializer', (serializers.ModelSerializer,), dct)

以上示例动态添加了一个字段,但您可以轻松地对其进行修改以添加字段列表。