对QS进行分组,获取最小值和最大值,并忽略生成的QS之间的条目

时间:2015-10-31 19:08:06

标签: python django postgresql

我有以下非常简单的模型:

class Event(models.Model):
    TYPE_CHOICES = (
        ('A', u'Alfa-event'),
        ('B', u'Beta-event'),
    )
    type = models.CharField(max_length=1, choices=TYPE_CHOICES)
    date = models.DateField()

为此模型创建以下条目:

>>> Event.objects.create(type="B", date="2015-01-23")
>>> Event.objects.create(type="B", date="2015-01-30")
>>> Event.objects.create(type="B", date="2015-02-03")
>>> Event.objects.create(type="B", date="2015-02-05")
>>> Event.objects.create(type="B", date="2015-02-06")
>>> Event.objects.create(type="B", date="2015-02-25")
>>> Event.objects.create(type="B", date="2015-03-21")
>>> Event.objects.create(type="B", date="2015-04-28")
>>> Event.objects.create(type="A", date="2015-07-05")
>>> Event.objects.create(type="A", date="2015-07-06")
>>> Event.objects.create(type="A", date="2015-07-07")
>>> Event.objects.create(type="A", date="2015-07-20")
>>> Event.objects.create(type="A", date="2015-08-01")
>>> Event.objects.create(type="B", date="2015-09-01")
>>> Event.objects.create(type="B", date="2015-09-03")
>>> Event.objects.create(type="B", date="2015-09-15")
>>> Event.objects.create(type="B", date="2015-09-16")
>>> Event.objects.create(type="A", date="2015-10-01")
>>> Event.objects.create(type="A", date="2015-10-14")
>>> Event.objects.create(type="A", date="2015-10-20")
>>> Event.objects.create(type="A", date="2015-10-31")

在一个视图中,我想实现下表(最好通过Queryset,以便我可以利用它的优势):

+-----------+------------+------------+
|   Type    |    From    |     To     |
+-----------+------------+------------+
| Alfa-type | 2015-10-01 | 2015-10-31 |
| Beta-type | 2015-09-01 | 2015-09-16 |
| Alfa-type | 2015-07-05 | 2015-08-01 |
| Beta-type | 2015-01-23 | 2015-04-28 |
+-----------+------------+------------+

基本上它按类型对所有Event进行分组,并且"记住" from和迄今,之后它显示在结果/表中。中间相同类型的所有事件都不是结果的一部分。

from日期可以作为具有相同连续事件类型的事件日期的最小值来实现。 to日期是这些活动日期的最大值。同样,不应该显示介于两者之间的事件。

这似乎是一个容易出问题的问题,但在过去的几天里,我一直在为此而烦恼。

  • 我尝试查看聚合,但这对我没有帮助,因为我将所有A或B类型的事件组合在一起,因此只在结果表中显示一次。
  • 我还看了一下手动查看QuerySet Events.objects.all(),但我已经卡在那里了。

有谁知道如何最好地接近这个?

在Python 2.7和Postgres上使用Django 1.8。

谢谢!

修改

我提出了以下解决方案。它有效,但我发现它有点乱砍。如果有人对此有所改进,我很高兴听到他们。

qs = Event.objects.all().order_by('-date')

event_from_ids = []
event_to_ids = []
event_to_ids.append(qs.first().id)

for current_event, next_event in zip(qs, qs[1:]):
    #print "current id:", current_event.id, " next id:", next_event.id
    if current_event.type != next_event.type:
        event_from_ids.append(current_event.id)
        event_to_ids.append(next_event.id)
event_from_ids.append(qs.last().id)

resulting_qs = qs.filter(id__in=event_from_ids)

# Using enumerate to keep track of the index while going over the loop
for idx, val in enumerate(resulting_qs):
    val.to_date = Event.objects.get(pk=event_to_ids[idx]).date

执行以下代码时(类似于视图中的代码):

for event in resulting_qs:
    print "Event type: ", event.type, " from: ", event.date, " to: ", event.to_date

...返回以下表格:

Event type:  A  from:  2015-10-01  to:  2015-10-31
Event type:  B  from:  2015-09-01  to:  2015-09-16
Event type:  A  from:  2015-07-05  to:  2015-08-01
Event type:  B  from:  2015-01-23  to:  2015-04-28

1 个答案:

答案 0 :(得分:0)

不确定这是否有效,因为您应该将开始日期和结束日期存储在数据库中,这样您就不需要根据事件类型对查询进行分组。

技术上如果你的数据库设计正确,这样的东西应该有用。

view.py

mydate = datetime.now() #or whatever date you need
events = event.objects.filter(date__lt=mydate, date__gt=mydate
    ).order_by('date')[:10]

template.html

{% for event in events %}
    {{ event.type }} | {{ event.date }}
{% endfor %}