【问题标题】:Issues with django rest framework using dynamic serializer使用动态序列化程序的 django rest 框架的问题
【发布时间】:2017-05-10 19:57:30
【问题描述】:

我有一个动态数据集,我试图通过动态创建序列化程序与 Django REST 框架一起使用,但它似乎没有处理我添加的动态属性。

代码如下:

-- views.py
class DynamicReadings(generics.ListAPIView):
    def get_serializer_class(self):
        site = self.kwargs['site']
        devices = Device.objects.filter(reader__site__slug=site).order_by('code')
        dyn_fields = ['x%s' % a.code for a in devices]
        return SerializerClassFactory(dyn_fields)

    def get_queryset(self):
        ...
        # the query is correct and returns data

-- serializers.py
def SerializerClassFactory(dyn_fields):
class DynamicSerializer(serializers.Serializer):
    read_at = serializers.DateTimeField()

    class Meta:
        fields = ('read_at')

    for f in dyn_fields:
        setattr(DynamicSerializer, f, serializers.FloatField())
    DynamicSerializer.Meta.fields += ','.join("'%s'" % f for f in dyn_fields)

    return DynamicSerializer

当我执行代码时,只有类定义中指定的属性(read_at)被序列化。动态属性似乎都没有工作。

例子:

[{"read_at":"2017-05-07T00:12:29Z"},{"read_at":"2017-05-08T00:12:30Z"}]

这是在shell中创建类后的输出:

>>> serializer = SerializerClassFactory(['x01', 'x02', 'x03'])
>>> serializer.__dict__
mappingproxy({'__module__': 'xxx.api.serializers', 
'Meta': <class 'xxx.api.serializers.SerializerClassFactory.<locals>.DynamicSerializer.Meta'>, 
'x02': FloatField(), '_declared_fields': OrderedDict([('read_at', DateTimeField())]), 
'__doc__': None, 'x01': FloatField(), 'x03': FloatField()})

另外,我试过了:

setattr(DynamicSerializer, f, property(serializers.FloatField()))
setattr(DynamicSerializer, f, type(serializers.FloatField()))

我不确定我做错了什么。

【问题讨论】:

    标签: python django python-3.x django-rest-framework dynamic-class


    【解决方案1】:

    这里只有字段是动态的,基本序列化器是一样的。为了使其正常工作,我们将仅更改 DynamicSerializer 上的字段

    serializers.py 中你会:

    class DynamicSerializer(serializers.Serializer):
        read_at = serializers.DateTimeField()
    
        class Meta:
            fields = ('read_at')
    
        def __init__(*args, dyn_fields=None, **kwargs):
            dyn_fields = dyn_fields or []
            for field in dyn_fields:
                self.fields[field] = serializers.FloatField()
    
            super(DynamicSerializer, self).__init__(*args, **kwargs)
    

    get_serializer_class 方法上的views.py 中,您可以使用return DynamicSerializer(dyn_fields=dyn_fields)

    更多信息请访问http://www.django-rest-framework.org/api-guide/serializers/#dynamically-modifying-fields

    【讨论】:

    • 我不得不更改 init 方法的签名:def __init__(self, dyn_fields=None, *args, **kwargs)。现在我收到错误“DynamicSerializer”对象不可调用。
    • 您遇到此问题是因为您需要不覆盖 get_serializer_class。看看这里 github.com/encode/django-rest-framework/blob/master/… get_serializer_class 期望返回一个类(可调用),而不是实例。你应该覆盖get_serializer()
    • 感谢您的帮助并为我指明了正确的方向。在这种情况下,您不能使用位置参数,因为它会导致问题。见这里link
    • class DynamicSerializer(serializers.Serializer): read_at = serializers.DateTimeField() def __init__(self, *args, **kwargs): dyn_fields = kwargs.pop('dyn_fields') for field in dyn_fields: self.fields[field] = serializers.FloatField() super(DynamicSerializer, self).__init__(*args, **kwargs)
    • def get_serializer(self, *args, **kwargs): site = self.kwargs['site'] device = Device.objects.filter(reader__site__slug=site).order_by('code') dyn_fields = ['x%s' % a.code for a in devices] kwargs['dyn_fields'] = dyn_fields return DynamicSerializer(*args, **kwargs)
    猜你喜欢
    • 1970-01-01
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    • 2016-05-04
    • 2017-10-03
    • 2019-05-20
    • 2022-01-08
    • 1970-01-01
    相关资源
    最近更新 更多