我仍然在努力与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尚未定义(并且看着它,显然没有。)坦白地说,我现在有些困惑,真的需要一些有关这部分代码的建议。
答案 0 :(得分:1)
简而言之:您可以通过 self.request
访问该请求。如果未给出请求,则self.request
为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
获得用户。
答案 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,
)
...