根据Djang中的项目分组进行分页

2024-04-20 06:50:59 发布

您现在位置:Python中文网/ 问答频道 /正文

对于使用Django/Python实现的网站,我们有以下要求:

在一个视图页面上,每个页面显示15条消息。当来自同一源的两个或多个消息在视图中彼此跟随时,应将它们组合在一起。在

可能不太清楚,但下面的例子可能是:

一个例子是(这次一个页面上有5条消息):

  Message1 Source1
  Message2 Source2
  Message3 Source2
  Message4 Source1
  Message5 Source3
  ...

这应显示为:

^{pr2}$

所以在每一页上都有固定数量的项目显示在页面上,有些项目已经重新组合。在

我们想知道如何创建一个Django或MySQL查询,以一种最佳且简单的方式查询这些数据。注意,使用的是分页,消息是按时间排序的。在

PS:由于SQL的特性,我不认为有一个简单的解决方案来解决这个问题,但有时复杂的问题可以很容易地解决


Tags: 项目django视图消息网站页面例子source1
2条回答

我有一个简单的,虽然不是完美的模板解决方案。在模板中,您可以使用regroup模板标记重新组合记录。重新组合后,可以隐藏来自同一源的连续记录:

{% regroup records by source as grouped_records %}
{% for group in grouped_records %}
  {% for item in group.list %}
    <li{% if not forloop.first %} style="display:none"{% endif %}>
       {{ item.message }} {{ iterm.source }}
       {% if forloop.first %}
         {% ifnotequal group.list|length 1 %}
           <a href="#" onclick="...">Show more from the same source...</a>
         {% endifnotequal %}           
       {% endif %}
    </li>
  {% endfor %}
{% endfor %}

如果不是为了一件事,这将是完美的:分页。如果你打算每页显示15个项目,而在一个页面上,前五个来自一个源,下五个来自另一个源,最后五个来自另一个源,那么页面上只有三个可见的项目。在

我看不出有什么好办法可以直接做你想做的事。如果您愿意接受一点去规范化,我建议使用一个预保存信号来将消息标记为在头部。在

#In your model
head = models.BooleanField(default=True)

#As a signal plugin:
def check_head(sender, **kwargs):
    message = kwargs['instance']
    if hasattr(message,'no_check_head') and message.no_check_head:
        return
    previous_message = Message.objects.filter(time__lt=message.time).order_by('-time')[0]
    if message.source == previous_message.source:
        message.head = False
    next_message = Message.objects.filter(time__gt=message.time).order_by('time')[0]
    if message.source == next_message.source:
        next_message.head = False
        next_message.no_check_head
        next_message.save()

然后,您的查询变得神奇地简单:

^{pr2}$

说实话…信号侦听器应该比我写的要复杂一点。在我的方法中有很多丢失同步/丢失更新的问题,这些问题的解决方案会因服务器而异(如果它是单处理、多线程的,那么python Lock对象应该可以满足您的需要,但是如果它是多处理的,然后您将真正需要实现基于文件或数据库对象的锁定)。此外,您还必须编写相应的删除信号侦听器。在

显然,这个解决方案涉及到添加一些数据库命中,但是它们是编辑的,而不是视图上的,这可能对您是有价值的。否则,可以考虑一个更粗糙的方法:抓取30个故事,在视图中循环,去掉那些你不想显示的,如果你还有15个,就展示它们,否则重复。绝对是一个可怕的最坏情况,但也许不是可怕的一般情况?在

如果您的服务器配置使用了多线程的单个进程,那么锁或RLock就可以做到这一点。下面是一个使用不可重入锁的可能实现:

import thread
lock = thread.allocate_lock()
def check_head(sender, **kwargs):
    # This check must come outside the safe zone
    # Otherwise, your code will screech to a hault
    message = kwargs['instance']
    if hasattr(message,'no_check_head') and message.no_check_head:
        return
    # define safe zone
    lock.acquire()
    # see code above
    ....
    lock.release()

同样,相应的删除信号也是至关重要的。在

编辑:许多或大多数服务器配置(如Apache)都将预处理,这意味着有几个进程正在进行。在这种情况下,上面的代码将是无用的。请参阅this page,了解如何开始与分叉进程同步。在

相关问题 更多 >