django:order_by和distinct OK;然后order_by另一个领域...... HowTo?

时间:2014-05-04 13:33:05

标签: python django postgresql distinct django-orm

我不知道怎么做......看起来很简单,但我无法做到......请给我一个提示。这是模型:

class PointOfInterest(models.Model):
    name = models.CharField(max_length=100)
    geom = geomodels.PointField(srid=4326)
    ...

class Event(models.Model):
    venue = models.ForeignKey('PointOfInterest',related_name='events')
    start = models.DateTimeField()
    ...

事件表包含许多事件,并且在同一PointOfInterest中可能存在多个事件。我的目标是选择从我今天开始的前10个事件(过去显然有事件)。对于每个PointOfInterest,新列表只有一个条目。所以我开始选择这些活动:

from django.db.models import Max, Min
from datetime import datetime, date, timedelta
from django.contrib.gis.measure import D
# this is my place...
pnt=Point(15.0,43.2)
# this is the date range...
start_date = datetime(date.today().year,date.today().month,date.today().day,0,0,0)
end_date = start_date + timedelta(days=30)
qs1 = Event.objects.filter(venue__geom__distance_lte=(pnt, D(km=10)))
qs2 = filter(start__range=(start_date, end_date))
qs2 = qs1.filter(start__range=(start_date, end_date))

列表现在包含所有请求的事件,但同一个地方也有多个事件......但我只需要即将发生的事件。主要问题是这个列表可能很大,我的最后一步是只获得10个即将发生的事件。我尝试使用distinct('venue'),但后来我不能命令('开始')。所以我不知道如何继续......

我也试过反过来......

qs1 = PointOfInterest.objects.filter(geom__distance_lte=(pnt, D(km=10)))
qs2 = qs1.annotate(minDate=Min('events__start'))
qs3 = qs2.filter(minDate__range=(start_date, end_date))

这个列表给了我所有PointOfInterest(在我的情况下为129 ...而前一个列表给了我137个事件......实际上在所选查询中有8个地方有2个事件,我需要保留每个地方只有即将到来的地方。最后我要order_by('start')并且只保留其中的一些。)

同样在这种情况下,我尝试了很多,但没有任何效果......任何人都可以提供帮助? 感谢

修改

几乎就在那里。根据EvilX的建议,我改变了选择,但是events__start__range=(start_date, end_date)在地点上运行,所以当我执行他建议的2个额外时,我得到了与每个地方相关的第一个事件(如果它在过去也是如此) )。我不得不稍微改变SQL查询。第一次尝试是这样的:

.extra(select={'event_pk': '
    SELECT start    
    FROM app_event_event 
    AS evt 
    WHERE evt.venue_id=app_place_pointofinterest.id AND evt.start >= \'2014/05/04\' 
    ORDER BY start 
    LIMIT 1'})

哪个有效...然后我尝试按照django文档将参数传递给SQL查询,如下所示:

.extra(select={'event_pk': '
    SELECT start 
    FROM app_event_event 
    AS evt
    WHERE evt.venue_id=app_place_pointofinterest.id AND evt.start >= %s 
    ORDER BY start 
    LIMIT 1'}, params=['2014/05/04']) 

但在这里我收到一个错误:StopIteration;我尝试了不同的组合,有和没有逃脱角色,但没有任何工作...所以我需要一些更多的建议。 感谢

1 个答案:

答案 0 :(得分:0)

尝试使用额外和两个查询。

points = PointOfInterest.objects.filter(geom__distance_lte=(pnt, D(km=10)), events__start__range=(start_date, end_date)).extra(select={'event_pk': 'SELECT event.id FROM app name_event AS event where event.venue_pk=appname_pointofinterest.id ORDER BY start LIMIT 1'}).extra(select={'event_start': 'SELECT event.start_date FROM app name_event AS event where event.venue_pk=appname_pointofinterest.id ORDER BY start LIMIT 1'}).order_by('event_start')[:10]
ids = []
for point in points:
    ids.append(point.event_pk)
events = Event.objects.select_related('venue').filter(pk__in=ids)