【问题标题】:django join-like expansion of queryset查询集的类似django join的扩展
【发布时间】:2023-03-16 16:04:01
【问题描述】:

我有一个Persons 列表,每个都有多个字段,我通常使用 object_list 通用视图过滤这些字段。每个人可以有多个Comments 附加到他们身上,每个人都有一个日期时间和一个文本字符串。我最终想要做的是可以选择根据日期过滤 cmets。

class Person(models.Model):
    name = models.CharField("Name", max_length=30)
    ## has ~30 other fields, usually filtered on as well

class Comment(models.Model):
    date = models.DateTimeField()
    person = models.ForeignKey(Person)
    comment = models.TextField("Comment Text", max_length=1023)

我想要做的是得到一个像

这样的查询集
Person.objects.filter(comment__date__gt=date(2011,1,1)).order_by('comment__date')

将该查询集发送到 object_list 并且只能查看按日期排序的 cmets,页面上只有这么多对象。

例如,如果“人 A”在 2010 年 12 月 12 日、2011 年 1 月 2 日、2011 年 1 月 5 日有 cmets,则“人 B”没有 cmets,而人 C 在 2010 年 1 月 3 日有评论,我会看到:

"Person A",   1/2  - comment
"Person C",   1/3  - comment
"Person A",   1/5  - comment

我强烈希望不必切换到基于 Comments.objects.filter() 的过滤,因为这会使我不得不在视图和模板中大量重复大部分代码。

现在,如果我尝试执行以下命令,我将得到一个返回的查询集(PersonA、PersonC、PersonA),但如果我尝试在模板中呈现它,每个人的 comment_set 将包含他们所有的 cmets,即使他们不是在日期范围内。

理想情况下,我可以将Person 查询集的comment_set 扩展为更大的查询集,该查询集可以根据注释进行排序和排序,并放入object_list 通用视图中。这通常在 SQL 中通过 JOIN 执行相当简单,但我不想放弃我在其他地方使用的 ORM。


好的,我的解决方案基本上就是 Comments.objects.filter();将模板拆分为以适当方式包含的单独文件,应用额外的上下文布尔值(如果为comment_date_filter,在视图中的所有人员引用之前应用适当的前缀字符串(即''或'person__'):

{% if comment_date_filter %}
   {% for obj in object_list %}
      {% with obj.person as p %}
        {% include "object_list_row.html" %}
      {% endwith %}
   {% endfor %}
{% else %}
   {% for obj in object_list %}
      {% with obj as p %}
        {% include "object_list_row.html" %}
      {% endwith %}
   {% endfor %}
{% endif %}

【问题讨论】:

    标签: python django join django-queryset


    【解决方案1】:

    您的另一个选择是将所有对象提取为 (Person, Date, Comment) 元组并在 Python 中对其进行排序。

    但是,我不知道您不想使用 Comment.objects.filter() 的原因是什么。这可能会相当快,尤其是当您的日期字段已编入索引时。

    【讨论】:

    • 它主要只是将视图和模板中的代码量增加一倍,并试图保持干燥,并期望有一个简单的解决方案,我只是忽略了允许我实现连接。 Django 让我根据评论日期(重复)订购医师,但不会让我看到它根据它进行排序的 cmets?这对我来说似乎很奇怪。我不想从评论中过滤的原因是我的模板和视图都是几 100 行,并且做了一些我不想以两种不同的方式实现的花哨的事情。
    • 我相信您的原始查询已关闭,Person.objects.filter(comment__date__gt=date(2011,1,1)).order_by('comment__date') 如果我对这将生成的 SQL 的理解是正确的,那么基本这将通过人们的第一条评论来订购。 comment_date_filter 和 comment_date_filter 有什么不同。为什么过滤与不过滤不同?我的意思是,为什么不在视图中这样做:if filtered: objects = Comments.filter(...).order_by(...) else: objects = Comments.order_by(...)
    猜你喜欢
    • 1970-01-01
    • 2013-03-11
    • 2014-09-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-21
    • 2018-02-10
    • 2014-05-23
    • 2019-01-16
    相关资源
    最近更新 更多