【问题标题】:Django dynamic filtersetDjango 动态过滤器集
【发布时间】:2016-05-30 00:37:45
【问题描述】:

所以我想从django-filter module 创建一个django filters.FilterSet,但我想动态添加它的属性。例如,如果我想动态添加SubName

class UsersInfoFilter(filters.FilterSet):
    Name=NumberFilter(lookup_type='gte')
    def __new__(self):
        self.SubName=NumberFilter(lookup_type='gte')
        self.Meta.fields.append('SubName')
    class Meta:
        model = UsersInfo
        fields = ['UserID', 'LanguageID', 'Name']

问题在于,FilterSet 是一个元类,一旦确定了类就会立即运行,因此在此之前没有任何地方可以动态添加项目。

我已经尝试将一个函数作为参数放入 filters.FilterSet class UsersInfo(AddObjects(filters.FilterSet)) 周围,它会准确返回通过的内容,但此时我无法引用 UsersInfoFilter,因为它还没有完成创建。

我还尝试将 UsersInfoFilter 创建为自己的基类,然后创建一个 class RealUsersInfoFilter(UsersInfoFilter, filters.FilterSet) 作为我的实际过滤器,但随后 FilterSet 只是抛出有关缺少名为字段的属性的警告。

python 中的类似乎没有任何类型的构造函数。我假设我必须对元类施展某种魔法,但我已经尝试了所有我能想到的组合并且束手无策。

【问题讨论】:

  • 您应该添加django-filter 标签以最大限度地提高获得答案的机会。
  • 你找到答案了吗?我被困在类似的事情上。
  • 不幸的是,解决方案从未出现过。
  • 看看这个有助于根据 url 参数在查询集上应用过滤器 github.com/manjitkumar/drf-url-filters

标签: python django multiple-inheritance metaclass django-filter


【解决方案1】:

您不能从 __init__ 方法更改 Meta 子类...有 2 个选项可以解决您的问题...

第一个 - 在所有模型字段上定义“宽”过滤器:

class UsersInfoFilter(filters.FilterSet):
    class Meta:
        model = UsersInfo

它将为您的所有模型字段创建默认过滤器。

二、定义动态字段:

class UsersInfoFilter(filters.FilterSet):
    name = NumberFilter(lookup_type='gte')

    def __init__(self):
        super(UsersInfoFilter, self).__init__()

        base_filters['subname'] = NumberFilter(name='subname', lookup_type='gte')

    class Meta:
        model = UsersInfo
        fields = ['user_id', 'language_id', 'name']

(我不知道这是否是你真正想要的——因为尽管“动态”添加字段——它应该被声明为静态——这里没有逻辑)

附言 为什么在属性和字段上使用 CamelCase?使用正确的 pep-8。

【讨论】:

    【解决方案2】:

    要动态选择FilterSet中的字段,我建议像这样创建一个FilterSet工厂:

    def filterset_factory(model, fields):
    
        meta = type(str('Meta'), (object,), {'model': model, 'fields': fields})
    
        filterset = type(str('%sFilterSet' % model._meta.object_name),
                     (FilterSet,), {'Meta': meta})
    
        return filterset
    

    然后像这样使用它:

    DynamicFilterClass = filterset_factory(model=MyModel, fields=[...])
    dynamic_filter = DynamicFilterClass(request.GET, queryset=instances)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-11
      • 1970-01-01
      • 1970-01-01
      • 2016-01-20
      • 1970-01-01
      • 2020-11-13
      • 2021-03-23
      相关资源
      最近更新 更多