ListView 中的 Django 过滤关系
Django filtering relation in ListView
给定模型
class TaskGroup(models.Model):
name = models.CharField(max_length=256)
class Task(models.Model):
name = models.CharField(max_length=256)
group = models.ForeignKey(TaskGroup, on_delete=models.CASCADE)
completed = models.BooleanField(default=False)
completed_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
和列表视图
class TaskGroupListView(ListView):
model = TaskGroup
我想显示具有相应任务的任务组列表。问题是 - 我只想显示用户尚未完成或已完成的任务,或者如果用户作为属性 user.type == "ADMIN"
设置显示所有组和所有任务。
现在我有一个看起来像这样的模板:
{% for taskgroup in object_list %}
<h1>{{ taskgroup.name }}</h1>
<ul>
{% for task in taskgroup.task_set.all %}
<li>{{ task.name }}</li>
{% endfor %}
</ul>
{% endfor %}
我知道我可以通过重写 get_queryset
来修改列表视图的查询集,例如:
def get_queryset(self):
if self.request.user == "ADMIN":
return TaskGroup.objects.all()
else:
...
但我不确定如何在 else 子句中过滤 TaskGroup
上的 Task
关系。
我考虑过为 Task
创建一个管理器子类,它可以根据我可以在模板中使用的 .completed
和 .completed_by
进行过滤,但这似乎违背了Django - 我想将所有逻辑保留在视图中(这可能离题很远,所以请纠正我,自从我触及 django/read 两勺 django 以来已经有一段时间了)。
有什么惯用的方法可以做到这一点吗?我应该完全放弃 ListView 并编写一些自定义逻辑吗?这里的任何指导都是有帮助的。谢谢。
您可以使用 prefetch_related
with a Prefetch
,它使用像这样的自定义过滤查询集:
from django.db.models import Prefetch, Q
def get_queryset(self):
if self.request.user.is_admin:
return TaskGroup.objects.all()
return TaskGroup.objects.prefetch_related(
Prefetch(
'task_set',
queryset=Task.objects.filter(Q(completed=False) | Q(completed_by=self.request.user))
)
)
这将获取所有 TaskGroup
以及相关 Tasks
(在 task_set
中)被那些尚未完成或当前用户已完成的筛选。
给定模型
class TaskGroup(models.Model):
name = models.CharField(max_length=256)
class Task(models.Model):
name = models.CharField(max_length=256)
group = models.ForeignKey(TaskGroup, on_delete=models.CASCADE)
completed = models.BooleanField(default=False)
completed_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
和列表视图
class TaskGroupListView(ListView):
model = TaskGroup
我想显示具有相应任务的任务组列表。问题是 - 我只想显示用户尚未完成或已完成的任务,或者如果用户作为属性 user.type == "ADMIN"
设置显示所有组和所有任务。
现在我有一个看起来像这样的模板:
{% for taskgroup in object_list %}
<h1>{{ taskgroup.name }}</h1>
<ul>
{% for task in taskgroup.task_set.all %}
<li>{{ task.name }}</li>
{% endfor %}
</ul>
{% endfor %}
我知道我可以通过重写 get_queryset
来修改列表视图的查询集,例如:
def get_queryset(self):
if self.request.user == "ADMIN":
return TaskGroup.objects.all()
else:
...
但我不确定如何在 else 子句中过滤 TaskGroup
上的 Task
关系。
我考虑过为 Task
创建一个管理器子类,它可以根据我可以在模板中使用的 .completed
和 .completed_by
进行过滤,但这似乎违背了Django - 我想将所有逻辑保留在视图中(这可能离题很远,所以请纠正我,自从我触及 django/read 两勺 django 以来已经有一段时间了)。
有什么惯用的方法可以做到这一点吗?我应该完全放弃 ListView 并编写一些自定义逻辑吗?这里的任何指导都是有帮助的。谢谢。
您可以使用 prefetch_related
with a Prefetch
,它使用像这样的自定义过滤查询集:
from django.db.models import Prefetch, Q
def get_queryset(self):
if self.request.user.is_admin:
return TaskGroup.objects.all()
return TaskGroup.objects.prefetch_related(
Prefetch(
'task_set',
queryset=Task.objects.filter(Q(completed=False) | Q(completed_by=self.request.user))
)
)
这将获取所有 TaskGroup
以及相关 Tasks
(在 task_set
中)被那些尚未完成或当前用户已完成的筛选。