Django ORM,按组/文件夹的最新项目/消息

时间:2016-05-06 14:03:14

标签: python django django-orm

我正在使用Django 1.8,我有一些模型:

class Folder(models.Model):
    title = models.CharField( max_length=255 )

class Message(models.Model):
    title = models.CharField( max_length=255 )
    folder = models.ForeignKey( Folder )

我需要,屏幕显示所有带有限制的最新消息(如10)的文件夹,如:

F1:    F2:   F3:
 m1     m3    m6
 m2     m4    ..
 m3     m5    ..
              m10

如何使用django-orm创建此查询?感谢。

2 个答案:

答案 0 :(得分:2)

您可以在property模型中添加Folder

class Folder(models.Model):
    title = models.CharField( max_length=255 )

    @property
    def latest_10_messages(self):
        # order by id decreasing and get top 10
        return self.message_set.order_by('-id')[:10]

然后,在您的模板中,您可以使用它:

{% for folder in folders %}
    {{ folder.name }}

    {% for msg in folder.latest_10_messages %}
        {{ msg.title }}
    {% endfor %}
{% endfor %}

更新以减少对数据库的查询次数:

如果您想减少查询次数,可以使用自定义查询集的Prefetch对象:

prefetch_query = Prefetch('message_set__title', queryset=Message.objects.all().order_by('-id'), to_attr='message_titles')
folders = Folder.objects.all().prefetch_related(prefetch_query)

然后在模板中使用slice获得前10名

{% for folder in folders %}
    {{ folder.name }}

    {% for msg in folder.message_titles|slice":10" %}
        {{ msg }}
    {% endfor %}
{% endfor %}

答案 1 :(得分:1)

要获得更好的效果,您可以尝试使用prefetch_related

# get the folders
folders = Folder.objects.all().prefetch_related('message_set')

# create a result list
result = []

# populate result list
result = [{'folder': f.title, 'messages': f.message_set.values('title').order_by('-id')[:10]} for f in folders]

# every f.message_set... won't hit database, because of prefetch_related

然后在你的模板中:

<ul>
  {% for res in result %}
    <li>
      {% for message in res.messages %}
        {{ message.title }}
      {% endfor %}
    </li>
  {% endfor %}
</ul>

或者您可以在模板中查看regroup

免责声明:此代码使用类似的模型结构进行测试,而不是模板,因此,您可能需要进行一些小的更改。以满足您的需求。