将附加属性传递给Djangofilter

2024-10-01 13:34:53 发布

您现在位置:Python中文网/ 问答频道 /正文

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

下面是一段代码片段来说明这个问题:

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

在本例中,缺少<model>-属性。如何将此信息从Project传递到筛选器


Tags: django模型selfidmodeltypecontentfilter
1条回答
网友
1楼 · 发布于 2024-10-01 13:34:53

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

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

在上面的示例中,超类分别是django_filters.BooleanFilterdjango_filters.Filter

使用^{}-方法,将关键字从kwargs字典中删除,同时我们可以将其保存以供进一步使用。由于content_type在初始化后从不更改,因此可以在__init__()中设置它

下面是上面代码的一个工作示例,其中Project是我要传递给过滤器的django模型:

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

对于我的特定用例,我正在寻找使用过滤器的模型,该模型通过queryset作为qs.model提供。代码段如下所示:

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

相关问题 更多 >