Django动态过滤器

时间:2016-02-18 02:02:53

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

所以我想从django filters.FilterSet创建django-filter module,但我想动态添加其属性。例如,如果我想动态添加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,因为它仍然不是&#39 ; t完成了创作。

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

对于python中的类,似乎没有任何类型的构造函数。我假设我必须用元类做一些魔法,但是我已经尝试了我能想到的每一个组合,并且最终处于智慧状态。

2 个答案:

答案 0 :(得分:0)

您无法从Meta方法更改__init__子类...有两种方法可以解决您的问题......

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

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']

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

P.S。 为什么CamelCase的属性和领域?使用适当的pep-8。

答案 1 :(得分:0)

要动态选择 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)