【问题标题】:Django: Generating a queryset from a GET requestDjango:从 G​​ET 请求生成查询集
【发布时间】:2011-04-29 23:44:11
【问题描述】:

我有一个使用 GET 方法的 Django 表单设置。每个值对应于 Django 模型的属性。生成查询的最优雅的方式是什么?目前这是我在视图中所做的:

def search_items(request):
    if 'search_name' in request.GET:
        query_attributes = {}

        query_attributes['color'] = request.GET.get('color', '')
        if not query_attributes['color']: del query_attributes['color']

        query_attributes['shape'] = request.GET.get('shape', '')
        if not query_attributes['shape']: del query_attributes['shape']

        items = Items.objects.filter(**query_attributes)

但我很确定有更好的方法来解决它。

【问题讨论】:

    标签: django django-views django-queryset


    【解决方案1】:

    嗯,你解决问题的基本方法看起来不错,但你写出来的方式看起来有点滑稽。我可能会这样做:

    def search_items(request):
        if 'search_name' in request.GET:
            query_attributes = {}
    
            color = request.GET.get('color', '')
            if color:
                query_attributes['color'] = color
    
            shape = request.GET.get('shape', '')
            if shape:
                query_attributes['shape'] = shape
    
            items = Items.objects.filter(**query_attributes)
    

    【讨论】:

      【解决方案2】:

      您可以使用列表组合和“感兴趣的参数”集来做到这一点:

      def search_items(request):
          if 'search_name' in request.GET:
              interested_params = ('color', 'shape')
              query_attrs = dict([(param, val) for param, val in request.GET.iteritems() 
                                  if param in interested_params and val])
      
              items = Items.objects.filter(**query_attrs)
      

      只是为了好玩(实际上不要这样做),您可以在一行中完成:

      def search_items(request):
          items = Items.objects.filter(
              **dict([(param, val) for param, val in request.GET.iteritems() 
                      if param in ('color', 'shape') and val])
          ) if 'search_name' in request.GET else None 
      

      【讨论】:

      • 只要确保你清理了输入。
      • @Andrew Sledge:你建议清理的攻击媒介是什么?
      • 永远不要相信用户输入。 Django 请求对象存储在字典中。字典可以保存任何类型的信息。因此,如果您期望某些字符串但得到其他“不健康”的字符串,则需要清理它们或丢弃它们。
      【解决方案3】:

      如果您希望它是完全动态的,您可以使用一点模型自省来找出您可以实际查询的字段,并仅使用这些字段进行过滤。

      虽然,这个解决方案不允许你在GET参数中使用__lookups,不知道你是否需要。

      def search_items(request):
          if 'search_name' in request.GET:
              all_fields = Items._meta.get_all_field_names()
              filters = [(k, v) for k, v in request.GET.items() if k in all_fields]
      
              items = Items.objects.filter(*filters)
      

      【讨论】:

        【解决方案4】:
        def search_items(request):
            try:
                items = Items.objects.filter(**dict([
                    (F, request.GET[F]) for F in ('color', 'shape')
                ]))
        
            except KeyError:
                raise Http404
        

        假设 'color' 和 'shape' 是必需的 GET 参数。出于安全原因,首选过滤参数的预定义元组。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-01-07
          • 2017-01-02
          • 1970-01-01
          • 2019-05-01
          • 2011-07-18
          • 2021-08-11
          • 2020-03-22
          • 1970-01-01
          相关资源
          最近更新 更多