在列表视图中显示多个查询集

LeL*_*uch 7 django django-templates django-models django-views

我正在尝试将具有多个模型的多个查询集显示为时间线,并按时间对它们进行排序,而不是在另一个查询集之后显示一个查询集,我当前的代码如下所示:

<div class="user-info col-md-8">
{% for obj in user.marks_set.all %}
                     <p>{{ obj.module }}</p> 
                      <p>{{ obj.grade }}</p>
                      <p>{{ obj.date }}</p>
{% endfor %}
{% for obj in events %}
                      {{ obj.content }}
{% endfor %}
</div>
Run Code Online (Sandbox Code Playgroud)

所有模型都有日期字段,我试图显示所有内容并按日期排序,而不是显示所有标记,然后显示所有事件

Pra*_*kar 7

虽然与核心问题无关,但由于这个答案因标题而出现,所以我将其发布给新手:

要从单个 ListView 返回多个查询集,如果您可以将所有查询集组合在一个变量中,那么它在 Django 中就变得可以接受了。简单的方法是使用字典。

例如:我需要从同一个模型中获取两个查询,一个是所有卖家,另一个是前 5 个卖家。所以在views.py 中:

class ViewName(ListView):
    model = ModelName
    template_name = "seller_info.html"
    context_object_name = 'sellers'

    def get_queryset(self):
        queryset = {'all_sellers': ModelName.objects.all(), 
                    'top_seller': ModelName.objects.all().filter(is_highest=True)[:5]}
        return queryset
Run Code Online (Sandbox Code Playgroud)

Seller_info.html 中,您可以通过以下方式访问每个查询集:

用于显示所有卖家:

{% if sellers %}
    {% for seller in sellers.all_sellers %}
      <p> {{ seller.name }} </p>
    {% endfor %}
{% endif %}
Run Code Online (Sandbox Code Playgroud)

用于显示 top_seller:

{% if sellers.top_seller %}
    {% for seller in sellers.top_seller %}
      <p> {{ seller.name }} </p>
    {% endfor %}
{% endif %}
Run Code Online (Sandbox Code Playgroud)

请注意,如果只有一个畅销书,那么也使用上述 html 格式,但修改查询集,如: 'top_seller': ModelName.objects.all().filter(is_highest=True)[:1]


LeL*_*uch 2

我这样做的方式是使用 itertools chain 和 attrgetter

from itertools import chain
from operator import attrgetter

class MyListView(ListView):
    template_name = 'list.html'
    def get_queryset(self):
        qs1 = Events.objects.all() #your first qs
        qs2 = Marks.objects.all()  #your second qs
        #you can add as many qs as you want
        queryset = sorted(chain(qs1,qs2),key=attrgetter('timestamp'),)
        return queryset
Run Code Online (Sandbox Code Playgroud)

从这篇文章“Combine 2 Django Querysets from Different Models”中得到了答案

编辑

#models.py
class Events(models.Model):
    ...
    timestamp = models.DateTimeField(auto_now=False, auto_now_add=True,)

class Marks(models.Model):

    ...
    timestamp = models.DateTimeField(auto_now=False, auto_now_add=True,)


#templates
 {% for item in queryset %}
 {% if item.anyfieldusniquetoqs1 %}
   #here goes all qs1 field you want to display
 {% else %}
   #here goes all qs2 field you want to display
 {% endfor %}
Run Code Online (Sandbox Code Playgroud)