如何从django-filters.FilterList

时间:2018-07-12 15:35:06

标签: django django-filter

我仍然在努力与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)  

这很好用。但是,我也想按当前用户筛选下拉筛选器(即Project查询集)。我的用户登录并通过身份验证后,我认为用户详细信息应附加到请求中。

根据django-filter文档

  

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

所以似乎请求就在那儿,但是我不知道如何将其作为FilterSet的参数来访问,也无法在文档中或旅行中的其他任何地方找到示例怎么做。因此,如果有人可以给我任何线索,我将非常感谢您的帮助。

修改

感谢Willem提供的信息和建议。非常感谢。但是我想我可能还没有清楚地说明自己。问题不在于过滤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尚未定义(并且看着它,显然没有。)坦白地说,我现在有些困惑,真的需要一些有关这部分代码的建议。

2 个答案:

答案 0 :(得分:1)

简而言之:您可以通过 self.request 访问该请求。如果未给出请求,则self.requestNone

该请求是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获得用户。

答案 1 :(得分:0)

要按request.user过滤项目列表,您需要提供callable as the queryset argument。我对您的项目不熟悉,但是代码应类似于:

def requested_projects(request):
    if request is None:
        return Projects.objects.none()
    return Project.objects.filter(deleted__isnull=True, user_fkey=request.user)


class MasterListFilter(django_filters.FilterSet):
    project = django_filters.ModelChoiceFilter(
        label='Projects',
        name='project_fkey',
        queryset=requested_projects,
    )
    ...