【问题标题】:How can I dynamically set Django filter in queryset如何在查询集中动态设置 Django 过滤器
【发布时间】:2020-11-13 03:40:08
【问题描述】:

我正在 React 中创建一个表,从我的 Django DB 中获取一些数据。
它有过滤器,如果需要,我希望他们调用 API 以获取结果。

问题是我必须复制很多行,而我很确定有更好的方法来做到这一点。

以下是部分代码:

        if ss_value and not es_value and not iv_value and not timestamp:
            queryset = DailyReport.objects.all().filter(station_departure=ss_value)
        elif not ss_value and es_value and not iv_value and not timestamp:
            queryset = DailyReport.objects.all().filter(station_arrival=es_value)
        elif not ss_value and not es_value and iv_value and not timestamp:
            queryset = DailyReport.objects.all().filter(is_virtual=iv_value)
        elif not ss_value and not es_value and not iv_value and timestamp:
            queryset = DailyReport.objects.all().filter(
                Q(timestamp__range=(min_dt, max_dt)) | Q(upload_timestamp__range=(min_dt, max_dt)))
            logger.debug(queryset)
        elif ss_value and es_value and not iv_value and not timestamp:
            queryset = DailyReport.objects.all().filter(station_departure=ss_value, station_arrival=es_value)
        elif ss_value and not es_value and iv_value and not timestamp:
            queryset = DailyReport.objects.all().filter(station_departure=ss_value, is_virtual=iv_value)

它会一直持续下去。

你有什么更清洁的方法吗??

谢谢你:)

【问题讨论】:

    标签: django django-queryset django-orm


    【解决方案1】:

    您可以使用** 使用字典解包。当您有过滤器列表时,将它们添加到字典中,然后将它们解压缩到查询集过滤器中。

    例如:

    Model.objects.filter(x=2, y=3)
    
    # equivalent to
    
    Model.objects.filter(**{"x":2, "y":3})
    

    所以你的代码可以这样完成:

        queryset_filters = {}    
        if ss_value:
           queryset_filters['station_departure'] = ss_value
        if es_value:
           queryset_filters['station_arrival'] = es_value
        .
        .
        .
        
        queryset = DailyReport.objects.filter(**queryset_filters)
    

    【讨论】:

      【解决方案2】:

      您缺少的技术与 django 的关系不大,而与 Python 的关系更大。

      def myfunc1(arg1, arg2):
          print(arg1, arg2)
      
      def myfunc2(arg1=None, arg2=None):
          print(arg1, arg2)
      
      mylist = ['val1', 'val2']
      mydict = {'arg1': 'val1', 'arg2': 'val2'}
      

      假设你有上述情况:

      myfunc1('val1', 'val2')
      myfunc1(*mylist)
      

      等价!同样:

      myfunc2('val1', 'val2')
      myfunc2(**mydict)
      

      也是等价的!​​p>

      您可以将列表传递给函数调用,就好像它们是带有单个 * 的位置参数一样,您可以将字典作为带有双 * 的关键字参数传递

      所以最终你想要做的是建立一个形式的事物字典:

      filter_kwargs = {
         'django_filter_kwarg_name': 'django_filter_value'
      }
      

      所以对你来说这可能是:

      # build up the dictionary (or maybe you can do this off the form, request.GET, etc
      filter_kwargs = {
          'station_departure': ss_value,
          'station_arrival': es_value,
          ....
      }
      # do something here to filter out the empty/None key/values
      filter_kwargs = {key: value if value for key, value in filter_kwargs.items}
      # now get the queryset
      queryset = DailyReport.objects.all().filter(**filter_kwargs)
      
      
      

      【讨论】:

      • 哦,非常感谢。我不知道从现在开始这个技巧会有很大的帮助! :)
      【解决方案3】:

      您可以尝试将表单操作分配给您的按钮:

      <form action="" method="post">
        <input type="submit" name="value1" value="Button Name" />
        <input type="submit" name="value2" value="Button Name" />
      </form>
      

      然后你就可以了

      if "value1" in request.POST:
          qs = DailyReport.objects.filter(station_departure="value1")
      

      请注意,您将需要按钮,因为如果只有一个并且 HTML 不允许这样做,则没有任何意义。

      Reference

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-20
        • 2021-03-23
        • 1970-01-01
        • 2010-10-25
        相关资源
        最近更新 更多