Django 类似连接的 queryset 扩展
我有一个包含多个Person
对象的列表,每个对象都有很多字段,我通常会用对象列表的通用视图来进行筛选。每个人可以有多个Comment
评论,每条评论都有一个时间和一段文字。最终我想做的是根据日期来筛选评论。
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')
然后把这个查询集发送到对象列表中,这样我就能看到按日期排序的评论,并且每页只显示一定数量的对象。
比如,如果“人A”的评论日期是2010年12月12日、2011年1月2日、2011年1月5日,“人B”没有评论,而“人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),但如果我在模板中渲染这个查询集,每个人的评论集都会包含他们所有的评论,即使那些评论不在日期范围内。
理想情况下,我希望有某种功能,可以把Person
查询集的comment_set
扩展成一个更大的查询集,这样可以根据评论进行排序,并放入对象列表的通用视图中。通常在SQL中用JOIN来做这件事很简单,但我不想放弃我在其他地方使用的ORM。
好的,我的解决方案基本上就是使用Comments.objects.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 %}
1 个回答
你还有一个选择,就是把所有的对象提取出来,变成 (Person, Date, Comment)
这样的组合,然后在Python里进行排序。
不过,我不太清楚你为什么不想用 Comment.objects.filter() 这个方法。其实这个方法应该会比较快,特别是如果你的日期字段有索引的话。