【问题标题】:Pass additional attribute to django-filter将附加属性传递给 django-filter
【发布时间】:2020-09-11 14:57:02
【问题描述】:

我将 django-filter 与 DRF 一起使用。我有一个favourite-model,它通过 GenericRelation 链接到其他几个模型。 为了过滤具有 favourite-flag 的条目,我创建了一个自定义 FavouriteFilter,并将其添加到相应的模型中。我想查询相应模型的content_type_id,以限制来自Favourite 的结果。但是,我不知道如何将model 传递给FavouriteFilter 中的过滤器方法。

这里有一个代码 sn-p 来说明这个问题:

class ProjectFilter(BaseFilter):

    favourite_only = FavouriteFilter()


class FavouriteFilter(django_filters.BooleanFilter):
    """
    A custom filter which returns a users favourites of an element
    """

    def __init__(self, *args, **kwargs):
        # gettext_lazy breaks the OpenAPI generation => use gettext instead
        kwargs['label'] = gettext("My favourites")
        super(FavouriteFilter, self).__init__(*args, **kwargs)

    def filter(self, qs, value):
        if value == True:
            user = get_current_user()
            content_type = ContentType.objects.get_for_model(<model>)
            return qs.filter(pk__in=Favourite.objects
                             .filter(owner_id=user)
                             .filter(content_type_id=content_type)
                             .values_list('object_id', flat=True)
                             )
        else:
            return qs

在此示例中,缺少 &lt;model&gt;-属性。如何将 Project 中的这些信息传递给过滤器?

【问题讨论】:

    标签: python django django-filter drf-queryset


    【解决方案1】:

    关键字参数可以传递给过滤器,但需要在调用 super() 方法之前从 kwarg-dict 中删除。否则它们会被传递给超类,超类的__init__()-方法不知道关键字并抛出TypeError

    TypeError: __init__() got an unexpected keyword argument 'model'
    

    在上面的例子中,超类是django_filters.BooleanFilter,分别是django_filters.Filter

    使用dict.pop()-方法,关键字从 kwargs-dictionary 中删除,同时我们可以保存它以供进一步使用。由于content_type在初始化后永远不会改变,所以已经可以在__init__()中设置了。

    这是上面代码的一个工作示例,其中Project 是我想要传递给过滤器的 django-model:

    class ProjectFilter(BaseFilter):
    
        favourite_only = FavouriteFilter(model=Project)
    
    
    class FavouriteFilter(django_filters.BooleanFilter):
        """
        A custom filter which returns a users favourites of an element
        """
    
        def __init__(self, *args, **kwargs):
            # gettext_lazy breaks the OpenAPI generation => use gettext instead
            kwargs['label'] = gettext("My favourites")
            model = kwargs.pop('model')
            self.content_type = ContentType.objects.get_for_model(model)
            super(FavouriteFilter, self).__init__(*args, **kwargs)
    
        def filter(self, qs, value):
            if value == True:
                user = get_current_user()
                return qs.filter(pk__in=Favourite.objects
                                 .filter(owner_id=user)
                                 .filter(content_type_id=self.content_type)
                                 .values_list('object_id', flat=True)
                                 )
            else:
                return qs
    

    对于我正在寻找使用过滤器的模型的特定用例,该模型可通过查询集以qs.model 获得。代码-sn-p 如下所示:

    class ProjectFilter(BaseFilter):
    
        favourite_only = FavouriteFilter()
    
    
    class FavouriteFilter(django_filters.BooleanFilter):
        """
        A custom filter which returns a users favourites of an element
        """
    
        def __init__(self, *args, **kwargs):
            # gettext_lazy breaks the OpenAPI generation => use gettext instead
            kwargs['label'] = gettext("My favourites")
            super(FavouriteFilter, self).__init__(*args, **kwargs)
    
        def filter(self, qs, value):
            if value == True:
                user = get_current_user()
                content_type = ContentType.objects.get_for_model(qs.model)
                return qs.filter(pk__in=Favourite.objects
                                 .filter(owner_id=user)
                                 .filter(content_type_id=content_type)
                                 .values_list('object_id', flat=True)
                                 )
            else:
                return qs
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-22
      • 2021-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多