如何在 Django 的 ListView 中输出通过其他两个不同模型的外键搜索的博客对象的选择?

问题描述 投票:0回答:1

我有三个这样的模型:

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 值对它们进行排序。我怎样才能做到这一点?

我已经在其他帖子中寻找解决方案,但找不到适合我的问题的解决方案。

django django-models django-views django-queryset
1个回答
0
投票

您的

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

对于像SQLiteOracleMySQL这样的数据库,这还不够,因为如果用户不是作者或评论者,只有当您既是作者又是评论者时,它才会返回

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

注意:通常使用

settings.AUTH_USER_MODEL
 [Django-doc] 来引用用户模型比使用
User
模型 [Django- doc]
直接。有关更多信息,您可以参阅文档的引用
User
模型
部分[Django-doc]

© www.soinside.com 2019 - 2024. All rights reserved.