遺憾的是沒有辦法(我所知道的。我看了相當困難),以避免使用一些一種原始的sql來完成你想要做的事(用你目前的模型;看到最後的另一個建議)。但是,您可以儘可能少地寫入原始sql,從而將影響降至最低。在實踐中,Django站點不需要跨不同數據庫移植。除非你打算在別處使用這個應用程序或公開發布它,否則你應該沒問題。
以下示例適用於sqlite。您可以可以保留數據庫類型到date
函數的映射,查找驅動程序的類型,並根據需要使用正確的函數替換函數。
>>> for stat in Stats.objects.all():
... print stat.created, stat.growth
...
2013-06-22 13:41:25.334262+00:00 3
2013-06-22 13:41:40.473373+00:00 3
2013-06-22 13:41:44.921247+00:00 4
2013-06-22 13:41:47.533102+00:00 5
2013-06-23 13:41:58.458250+00:00 6
2013-06-23 13:42:01.282702+00:00 3
2013-06-23 13:42:03.633236+00:00 1
>>> last_stat_per_day = Stats.objects.extra(
select={'the_date': 'date(created)' }
).values_list('the_date').annotate(max_date=Max('created'))
>>> last_stat_per_day
[(u'2013-06-22', datetime.datetime(2013, 6, 22, 13, 41, 47, 533102, tzinfo=<UTC>)), (u'2013-06-23', datetime.datetime(2013, 6, 23, 13, 42, 3, 633236, tzinfo=<UTC>))]
>>> max_dates = [item[1] for item in last_stat_per_day]
>>> max_dates
[datetime.datetime(2013, 6, 22, 13, 41, 47, 533102, tzinfo=<UTC>),
datetime.datetime(2013, 6, 23, 13, 42, 3, 633236, tzinfo=<UTC>)]
>>> stats = Stats.objects.filter(created__in=max_dates)
>>> for stat in stats:
... print stat.created, stat.growth
...
2013-06-22 13:41:47.533102+00:00 5
2013-06-23 13:42:03.633236+00:00 1
我在這裏寫之前,這只是一個單一的查詢,但我撒謊 - 在values_list需要轉換到只返回MAX_DATE爲連續查詢,這意味着運行的語句。儘管只有2個查詢,但它會比N + 1函數好得多。
非便攜式位是這樣的:
last_stat_per_day = Stats.objects.extra(
select={'the_date': 'date(created)' }
).values_list('the_date').annotate(max_date=Max('created'))
使用extra
並不理想,但這裏的原始的SQL語句簡單,很好地適合於數據庫驅動程序相關的替代品。只需要更換date(created)
。如果你喜歡,你可以用自定義管理器的方法把它包裝起來,然後你可以在一個位置成功地抽象出這個混亂。
另一種方法是隻在模型中添加一個DateField
,然後根本不需要額外使用。您只需將values_list
呼叫替換爲values_list('created_date')
,完全刪除extra
,然後每天給它打電話。成本顯而易見 - 需要更多的存儲空間。這對於爲什麼在同一模型上有Date
和DateTime
字段也是非直觀的。保持兩者同步也可能造成問題。
只是爲了得到這個清晰的在我的腦海;如果你想要每一天的最新消息 - 在你的榜樣中你會不想要200和222增長? – Ewan
是的,沒錯。我糾正了它;) – Jannis