代码之家  ›  专栏  ›  技术社区  ›  rrauenza

在django过滤器中使用\ in进行自定义查询

  •  0
  • rrauenza  · 技术社区  · 7 年前

    我用的是django过滤器1.1.0。我需要编写一个使用自定义查询的过滤器,但在其中它可以选择 __in 后缀。

    这是我的解决方案,但我禁不住希望有一种稍微更干净的方法来实现这一点,类似于 id 是指定的--可能对bar和 'exact' '__in' 作为查找参数传入。

    class FooFilter(filters.FilterSet):
    
        bar_id = filters.CharFilter(method='filter_bar_id', label='Bar')
        bar_id__in = filters.CharFilter(method='filter_bar_id__in', label='Bar In')
    
    
        def filter_bar_id(self, queryset, name, value):
            return queryset.filter(
                Q(abc__xyz__bar=value) |
                Q(def__xyz__bar=value)).distinct()
    
        def filter_bar_id__in(self, queryset, name, value):
            bars = value.split(',')
            return queryset.filter(
                Q(abc__xyz__bar__in=bars) |
                Q(def__xyz__bar__in=bars)).distinct()
    
        class Meta:
            model = Foo
            fields = {
                'id': ['exact', 'in'],
                'bar_id': ['exact'],
                'bar_id__in': ['exact'],
            }
    

    Django过滤器是否有更本土化的方法?或者这就是实现这一目标的方法吗?

    还有一个stackoverflow问题使用 bar_id= 允许两者 ?bar_id=1 ?bar_id=1,2,3,4 . 为了保持一致性,我的django过滤器(比如 ?id ?id__in 我不想这样做。

    1 回复  |  直到 7 年前
        1
  •  0
  •   Sherpa    7 年前

    你可以利用 BaseInFilter 的验证逻辑,它将以逗号分隔的输入值转换为值列表。从那里,您的自定义筛选方法可以根据值的类型进行切换。

    也就是说,我认为这个解决方案并不一定比你现在拥有的更好。此外,这通常不适用于其他查找表达式。在这种情况下,您只能碰巧打开类型。

    class CharListFilter(filters.BaseInFilter, filters.CharFilter):
        pass
    
    
    class FooFilter(filters.FilterSet):
        bar_id = filters.CharFilter(method='filter_bar_id', label='Bar')
        bar_id__in = filters.CharListFilter(method='filter_bar_id', label='Bar In')
    
        def filter_bar_id(self, queryset, name, value):
            if isinstance(value, list):
                return queryset.filter(
                    Q(abc__xyz__bar__in=value) |
                    Q(def__xyz__bar__in=value)).distinct()
            return queryset.filter(
                Q(abc__xyz__bar=value) |
                Q(def__xyz__bar=value)).distinct()