首页 > 解决方案 > 如何从 django-filters.FilterList 获取请求参数

问题描述

我还在为 django-filter 苦苦挣扎。我在下面定义了我的过滤器

class MasterListFilter(django_filters.FilterSet):
    project = django_filters.ModelChoiceFilter(
        label='Projects',
        name='project_fkey',
        queryset=Project.objects.filter(deleted__isnull=True)
        )

    class Meta:
        model = Task
        fields = ['project']

    @property
    def qs(self):
        parent = super(MasterListFilter, self).qs
        user = get_current_user()        
        return parent.filter(master=True, deleted__isnull=True, user_fkey=user.id)  

这工作得很好。但是,我还想按当前用户过滤下拉过滤器(即项目查询集)。由于我的用户已登录并通过身份验证,我相信用户详细信息应附加到请求中。

根据 django-filter 文档

FilterSet 可以使用可选的请求参数进行初始化。如果传递了请求对象,则您可以在过滤期间访问该请求。这允许您按请求的属性进行过滤,例如当前登录的用户或 Accepts-Languages 标头。

所以看起来请求就在那里,但我无法弄清楚如何将它作为 FilterSet 的参数来访问,我也无法在文档或旅行中的其他任何地方找到关于如何访问的任何示例做。因此,如果有人可以给我任何线索,我真的很感激帮助。

编辑

感谢威廉提供的信息和建议。非常感谢。但是我想我可能没有清楚地解释自己。问题是没有过滤 qs

@property
    def qs(self):
        parent = super(MasterListFilter, self).qs
        user = get_current_user()        
        return parent.filter(master=True, deleted__isnull=True, user_fkey=user.id)

尽管我将按照建议将其更改为使用 self.request.user 并捕获任何无请求的请求,但此位工作正常。这部分返回在我的 hmtl 页面中呈现的结果表。在这种情况下,它是属于各种项目的任务列表。我想要做的是在页面顶部为用户提供一个下拉列表,其中包含他们可以选择的项目列表,从而按单个项目过滤结果表。(项目是父模型。)这部分代码:

class MasterListFilter(django_filters.FilterSet):
    project = django_filters.ModelChoiceFilter(
        label='Projects',
        name='project_fkey',
        queryset=Project.objects.filter(deleted__isnull=True)
        )

确实做到了这一点,因为它提供了所有项目的列表,在这种情况下,没有被删除。不幸的是,用户可以创建自己的项目,每个项目都有一个外键返回给创建它的用户。因此,除了显示没有被删除的项目之外,我还想只显示属于当前用户的项目。

毫无疑问,我在这里遗漏了一些东西,但我的理解是 django_filters.FilterSet 将请求作为属性,但是如果我尝试在课程的这一部分中使用 'user = self.request.user',我会收到一条错误消息self 没有定义(看着它,它显然没有。)坦率地说,我现在有点难过,真的需要一些关于这部分代码的建议。

标签: djangodjango-filter

解决方案


简而言之:您可以使用self.request. 如果没有给出请求,那么self.requestis None

请求是 的一个属性self。因此,您可以通过以下方式获得self.request.user

@property
def qs(self):
    parent = super(MasterListFilter, self).qs
    user = self.request.user  # unsafe (!) since request can be None!
    return parent.filter(master=True, deleted__isnull=True, user_fkey=user.id) 

但是请注意,请求可以是None. 所以最好防止这种情况,比如:

@property
def qs(self):
    parent = super(MasterListFilter, self).qs
    if self.request:
        user = self.request.user
    else:
        user = None
    if user and user.is_authenticated():
        return parent.filter(master=True, deleted__isnull=True, user_fkey=user.id) 
    else:
        # do something if no request, or no logged in user
        # for example
        return parent.filter(master=True, deleted__isnull=True)

或者以更紧凑的形式:

@property
def qs(self):
    parent = super(MasterListFilter, self).qs
    filters = dict(master=True, deleted__isnull=True)
    user = getattr(self.request, 'user', None)
    if user and user.is_authenticated():
        filters['user_fkey'] = user.id
    return parent.filter(**filters)

由于获取用户是一个相当常见的操作,我们可以为此实现一个mixin

class UserFilterMixin(object):

    @property
    def current_user(self):
        return getattr(self.request, 'user', None)

然后,您可以使用 mixin,从而获得具有self.current_user.


推荐阅读