ListView中的Django过滤关系



给定模型

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子句中过滤TaskGroups上的Task关系。

我曾想过为Task创建一个管理器子类,它可以基于.completed.completed_by进行过滤,我可以在模板中使用,但这似乎违背了Django的理念——我想保留所有的逻辑(这可能太离谱了,所以请纠正我,我已经有一段时间没有接触Django/read两勺Django了(。

有什么惯用的方法吗?我应该完全放弃ListView并编写一些自定义逻辑吗?这里的任何指导都是有用的。谢谢

您可以将prefetch_relatedPrefetch一起使用,后者使用如下自定义过滤查询集:

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))
)
)

这将使具有相关Taskss(在task_set中(的所有TaskGroups被当前用户尚未完成或已完成的那些过滤掉。

最新更新