【问题标题】:Django DRF ListField to deserialize list of ids in GET's queryparamsDjango DRF ListField 反序列化 GET 查询参数中的 id 列表
【发布时间】:2015-09-14 00:21:30
【问题描述】:

尝试使用 DRF 的 ListField 选项来反序列化查询参数中的值列表(以下示例中的应用程序)。我很难让它工作。在网上找不到示例。希望有人帮忙。

api/getAppStats/?applications=one,two,three

class MySerializer(serializers.Serializer):
 applications = serializers.ListField(child=serializers.CharField())
 start_date = serializers.DateField(default=(datetime.datetime.utcnow() - datetime.timedelta(days=30)).date().isoformat())
 end_date = serializers.DateField(default=datetime.datetime.utcnow().date().isoformat())

class SomeView(generics.GenericAPIView):
 """

 """
 permission_classes = [AllowAny]
 serializer_class = MySerializer

 def get(self, request, *args, **kwargs):

    """ 
    Just return query params..
    """
    serializer = MySerializer(data=request.query_params)

    if not serializer.is_valid():
        return Response({'stats':'invalid input data'})

    return Response({'stats':serializer.data})

我看到的只有这个 -

 {
            "stats": {
                "applications": [],
                "start_date": "2015-05-27",
                "end_date": "2015-06-26"
            }
        }

我是否以不正确的方式发送输入参数?我错过了一些微不足道的事情吗?

谢谢!

【问题讨论】:

    标签: django rest get django-rest-framework


    【解决方案1】:

    为同一个键发送多个参数的标准方法是两次使用相同的键名。

    你可以这样做:

    /getAppStats/?applications=one&applications=two&applications=three
    

    此外,您的服务器将以数组形式接收应用程序,即 applications[] 而不是 applications

    class SomeView(generics.GenericAPIView):
     """
    
     """
     permission_classes = [AllowAny]
     serializer_class = MySerializer
    
     def get(self, request, *args, **kwargs):
    
        """ 
        Just return query params..
        """
    
        # get the applications list
        applications = request.query_params.getlist('applications[]')
    
        # create a dictionary and pass it to serializer
        my_data = {'applications': applications, ...}
    
        serializer = MySerializer(data=my_data)
    
        if not serializer.is_valid():
            return Response({'stats':'invalid input data'})
    
        return Response({'stats':serializer.data})
    

    【讨论】:

    • 谢谢!这可行,但我想避免代码手动从查询参数中提取这些值并将其再次传递给序列化程序。我期待序列化程序为我做到这一点。
    • 另外,如果我想一次获取更多应用程序(比如 20 个或更多)的信息,URL 会不会显得冗长且多余?
    • 如果序列化器字段为applications[],序列化器将能够从查询参数中提取这些值。由于我们发送给序列化器的数据有applications[] 键,但序列化器中定义了applications 字段,它将无法获取applications 键的初始数据。
    • 是的,如果您使用一般方法,url 会变长,但如果 url 的长度小于 2k 个字符,它仍然有效且允许。检查此链接以获取 url 长度限制。 stackoverflow.com/questions/417142/…
    【解决方案2】:

    这已得到解答,但我也在寻找一种解决方案,该解决方案涉及通过使用 getlist 从请求中获取值来重构序列化程序数据(否则有什么意义)。

    如果您使用 ListField(并且可能还使用 many=True),则其中有处理列表的代码,问题是您在似乎会导致“ids []”语法弄乱序列化程序的客户端。

    Here 是我将使用的解决方案。

    【讨论】:

    • 不是ids[] 查询参数的格式标准。默认情况下,浏览器以这种格式提交 HTTP 表单帖子。我很惊讶 DRF 没有处理这个问题。
    【解决方案3】:

    但我想避免代码手动从查询参数中提取这些值并将其再次传递给序列化程序。我期待序列化程序为我做到这一点。 – 萨蒂什

    我也希望序列化程序为我执行此操作,但我还没有找到。此外,我将这个 query_params 列表用于 django-filterMultipleChoiceFilterModelMultipleChoiceFilter,所以 DRF ListField 对我不起作用。

    在我的项目中,Android 请求没有[],而只有IOS 请求带有[]

    我的解决方案是在request.query_paramsrequest.data中添加一个装饰器来添加数据。

    def update_get_list_params(func):
        def wraps(self, request, *args, **kwargs):
            request.query_params._mutable = True
            request.data._mutable = True
            for key in list(request.query_params.keys()):
                # Make sure you know this will not influence the other query_params
                if key.endswith('[]'):
                    new_key = key.split('[]')[0]
                    value = request.query_params.getlist(key)
                    if value:
                        request.query_params.setlist(new_key, value)
            for key in list(request.data.keys()):
                if key.endswith('[]'):
                    new_key = key.split('[]')[0]
                    value = request.data.getlist(key)
                    if value:
                        request.data.setlist(new_key, value)
            return func(self, request, *args, **kwargs)
        return wraps
    
    
    @update_get_list_params
    def get(self, request, *args, **kwargs):
         pass
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-23
      • 2018-06-29
      • 2021-05-09
      • 2021-12-27
      • 1970-01-01
      • 2022-12-03
      • 2013-11-02
      相关资源
      最近更新 更多