我有三个这样的模型:
1:
class Blog(models.Model):
title = models.CharField()
published = models.DateField()
...
2:
class AuthorList(models.Model):
blog = models.ForeignKey(Blog)
author = models.ForeignKey(User)
lastTimeEdited = models.DateTimeField()
...
3:
class CommentsList(models.Model):
blog = models.ForeignKey(Blog)
commentAuthor = models.ForeignKey(User)
commentPosted = models.DateTimeField()
...
我的基于类的 ListView 看起来像这样:
class DashboardView(LoginRequiredMixin, ListView):
model = Blog
template_name = 'app/dashboard.html'
paginate_by = 5
def get_queryset(self) -> QuerySet[Blog]:
user = self.request.user
author = #HERE I want a queryset of all blogs, where the requested user is one of the authors.
commentator = #HERE I want a queryset of all blogs, where the requested user is one of the commentators.
blogs = author|commentator
return blogs.order_by(#HERE I want to order them by the lastTimeEdited-Field or the commentPosted-Field)
所以我想以一种或另一种方式列出用户必须处理的所有博客。如果用户是作者,我还想按 lastTimeEdited 值对它们进行排序;如果用户是评论者,我还想按 commentPosted 值对它们进行排序。我怎样才能做到这一点?
我已经在其他帖子中寻找解决方案,但找不到适合我的问题的解决方案。
您的
AuthorList
模型充当 Blog
和 User
之间多对多关系的联结表。您可以使用以下命令在 ManyToManyField
模型上跨越 Blog
[Django-doc]:
class Blog(models.Model):
# …
authors = models.ManyToManyField(
settings.AUTH_USER_MODEL,
through='AuthorList',
related_name='authored_blogs',
)
commenters = models.ManyToManyField(
settings.AUTH_USER_MODEL,
through='CommentsList',
related_name='commented_blogs',
)
这使得查询变得更加容易,因为我们可以使用:
from django.db.models import Q
class DashboardView(LoginRequiredMixin, ListView):
model = Blog
template_name = 'app/dashboard.html'
paginate_by = 5
def get_queryset(self) -> QuerySet[Blog]:
return Blog.objects.filter(
Q(authors=request.user) | Q(commenters=request.user)
).order_by(???)
.annotate(…)
[Django-doc] 确定最后一个作者和/或评论时间,然后使用这个:
from django.db.models import Greatest, Max, Q
class DashboardView(LoginRequiredMixin, ListView):
model = Blog
template_name = 'app/dashboard.html'
paginate_by = 5
def get_queryset(self) -> QuerySet[Blog]:
return (
Blog.objects.filter(
Q(authors=request.user) | Q(commenters=request.user)
)
.annotate(
latest_edit=Greatest(
Max('authorlist__lastTimeEdited'),
Max('commentslist__lastTimeEdited'),
)
)
.order_by('-latest_edit')
)
对于像SQLite、Oracle和MySQL这样的数据库,这还不够,因为如果用户不是作者或评论者,只有当您既是作者又是评论者时,它才会返回
NULL
。评论者,这会起作用。我们可以通过 Coalesce
[Django-doc]: 以一种非常丑陋的方式解决这个问题
from django.db.models import Coalesce, Greatest, Max, Q
class DashboardView(LoginRequiredMixin, ListView):
model = Blog
template_name = 'app/dashboard.html'
paginate_by = 5
def get_queryset(self) -> QuerySet[Blog]:
return (
Blog.objects.filter(
Q(authors=request.user) | Q(commenters=request.user)
)
.annotate(
latest_edit=Greatest(
Coalesce(
Max('authorlist__lastTimeEdited'),
Max('commentslist__lastTimeEdited'),
),
Coalesce(
Max('commentslist__lastTimeEdited'),
Max('authorlist__lastTimeEdited'),
),
)
)
.order_by('-latest_edit')
)
[Django-doc] 来引用用户模型比使用settings.AUTH_USER_MODEL
模型 [Django- doc]直接。有关更多信息,您可以参阅文档的引用User
模型部分[Django-doc]。User