django 调用之间的动态串行化程序Meta状态污染

vnjpjtjt  于 2023-10-21  发布在  Go
关注(0)|答案(1)|浏览(125)

我有一个动态序列化器,我将API调用的参数传递到序列化器中,以从相关的模型类中筛选特定的字段。我通过利用序列化器的__init__函数直接设置self.Meta.fields来实现这一点,否则这是我配置的默认字段集。给定一个有3个字段iddescriptiontrigger的模型,当我进行一个未过滤的调用/api/endpoint时,我得到了我所期望的,一个包含模型中所有字段的json对象列表。然后,当我进行一个过滤调用时,即/api/endpoint?fields=id,我也得到了我所期望的结果,一个只包含id字段的列表结果。然而,当我进行另一个未过滤的调用时,我仍然得到一个只有id字段的对象列表。从现在开始我唯一能得到我想要的就是打一个新的过滤电话。下面是我的序列化器代码。

class BaseSerializer(serializers.ModelSerializer):
    # id comes from `serializers.ModelSerializer`
    description = DescriptionSerializer()
    trigger = TriggerSerializer()

class SerializerA(BaseSerializer):

    def __init__(self, *args, **kwargs):
        fields = kwargs.pop("fields", None)
        super().__init__(*args, **kwargs)
        if fields:
            self.Meta.fields = fields <--- this does NOT reset between calls

    class Meta:
        model = ImplIdDescriptionTriggerModelA  # there are more ImplModels...
        fields = '__all__'

class ParameterCaptureSerializer(BaseSerializer):

    class Meta:
        model = BaseIdDescriptionTriggerModel
        fields ='__all__'

    def to_representation(self, instance):
        fields = None  <--- I could set this to DEFAULT_FIELDS and fix the problem, but what about the Meta state between calls? Whats that about?
        request = self.context.get("request")
        if request:
            params = request.query_params.get("fields")
            if params:
                # parses params and checks them against a set of allowed values or throws
                # an rest_framework exception with a response showing allowed fields
                fields = parse_fields(field_param=params, allowed=ALLOWED_FIELDS)

        if isinstance(instance, ImplIdDescriptionTriggerModelA):
            return SerializerA(instance=instance, fields=fields, context=self.context).data
        elif isinstance(instance, ImplIdDescriptionTriggerModelB):
            return SerializerB(instance=instance, fields=fields, context=self.context).data
        # new document subtypes must be added here
        else:
            raise NotImplementedError

我认为唯一有意义的解决方案是将字段默认为ALLOWED_FIELDS,以解决这个问题,而不是引入并发问题。

bcs8qyzn

bcs8qyzn1#

首先,如果您在__init__上更改self.META-您将更改所有示例的对象Meta。
第二-DRF文档中的信息是错误的!!https://www.django-rest-framework.org/api-guide/serializers/#dynamically-modifying-fields-这是错误的解决方案。
在第三-我解决你的问题在我的谈话有:https://youtu.be/IycQNgzFKwE?si=rbucOYDy-xK5jzfU&t=170
最后,工作解决方案:

class DynamicFieldsSerializer(ModelSerializer):
    """Takes an additional `fields` argument"""

    def __init__(self, *args, **kwargs):
        fields = kwargs.pop('fields', None) or self.Meta.fields
        self.Meta = type('Meta', (self.Meta,) {'fields' : fields})
        super().__init__(*args, **kwargs)

相关问题