也许这实际上是一个错误,但由于没有找到任何暗示它已知的东西,我会假设我做错了。
我有一个模型,Study,有一个datetime字段以及描述优先级的对象的外键(基本上是一个名称/数字对,这样一个人可以按编号排序并按名称查看)。
我想首先按优先级排序研究对象(首先将它们分组为更高的优先级),然后按日期时间排序,最早的是第一个。通过这种方式,Stat将位于列表的顶部,具有最早的第一个等等。
使用我的测试数据库,这是一个sqlite,这可以正常工作:
ordered = ordered = models.Study.objects.all().order_by('arrived').order_by('-priority__priority')
for study in ordered:
print(study.arrived, study.priority)
(datetime.datetime(2013, 5, 15, 23, 22, tzinfo=<UTC>), <StudyPriority: STAT>)
(datetime.datetime(2013, 5, 15, 23, 20, 51, 948639, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 15, 23, 21, 6, 674582, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 15, 23, 21, 21, 86984, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 15, 23, 21, 36, 234965, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 15, 23, 21, 59, 618850, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 15, 23, 22, 18, 991499, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 15, 23, 22, 26, 229715, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 15, 23, 22, 31, 150896, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 15, 23, 22, 35, 379259, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 15, 23, 22, 43, 207465, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 15, 23, 31, 42, 176697, tzinfo=<UTC>), None)
另一方面,使用生产数据库(postgres),事情......出错了:
ordered = models.Study.objects.all().order_by('arrived').order_by('-priority__priority')
for study in ordered:
print(study.arrived, study.priority)
(datetime.datetime(2013, 5, 29, 22, 31, 45, tzinfo=<UTC>), None)
(datetime.datetime(2013, 5, 29, 22, 36, 15, tzinfo=<UTC>), <StudyPriority: STAT>)
(datetime.datetime(2013, 5, 29, 22, 36, 20, 520912, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 29, 22, 35, 18, 784721, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 29, 22, 35, 44, 540762, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 29, 22, 35, 51, 355645, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 29, 22, 35, 56, 800284, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 29, 22, 36, 2, 190325, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 29, 22, 36, 15, 137803, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 29, 22, 31, 44, 759514, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 29, 22, 37, 52, 264583, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 29, 22, 37, 54, 191852, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 29, 22, 37, 56, 385968, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 29, 22, 37, 57, 865427, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 29, 22, 38, 1, 959433, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 29, 22, 38, 4, 748306, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 29, 22, 36, 57, 562198, tzinfo=<UTC>), <StudyPriority: LOW>)
(datetime.datetime(2013, 5, 29, 22, 34, 37, 909631, tzinfo=<UTC>), <StudyPriority: LOW>)
最明显的烦恼是,无论出于何种原因,postgres首先按此顺序选择“null”对象。 'priority__priority'是数字优先级值,最高=最高(因此在这种情况下,null被视为无穷大,而在sqlite中它被视为-infinity)。这不是一个大问题,很容易实现一个恼人的解决方法来手动将它们移到底部。
真正的问题是日期时间似乎没有排序!在“低”优先级对象中,时间遍布地图。
这可能是ORM中的某种错误,还是我做了一些可识别错误的事情而不是sqlite的问题?
答案 0 :(得分:1)
我想你想这样做:
ordered = models.Study.objects.order_by('arrived', '-priority__priority')
https://docs.djangoproject.com/en/dev/ref/models/querysets/#order-by
答案 1 :(得分:1)
monokut关于如何正确链接order_by的答案是等式的一部分,另一部分是优先级_优先级NOT NULL。
您正在尝试对NULLable字段进行排序 - 这始终是特定于实现的monkeywrench。在上面你试图弄清楚为什么NULL是第一个或最后一个。它的整理在数据库之间是任意的,不是因为它“等于无穷大”,而是因为它不等于任何,甚至本身。 (顺便说一句,在Postgres中,如果你发出了一个raw()查询,你可以指定NULLS LAST或NULLS FIRST来获得你想要的东西,但是Django没有为它提供ORM快捷方式。)
如果你需要对列进行排序,可靠的方法是使字段为NOT NULL并为其提供一个默认值,明确表示“未定义”或“最后一个位置”,并在每个其他之前/之后对该值进行排序值,以便以可预测的方式进行排序。在更深层次的geek术语中,这是一个域/类型问题,并且您尝试在不包含它作为成员而不是显式“底部”值的域中对None类型进行排序。
在您的示例中,我将创建一个名为“LOWEST”的新优先级类型,将其设置为模型字段的默认值,并将priority__priority设置为1000或0,具体取决于“LOWEST”相对于“LOW”的含义。然后用LOWEST替换NULL的每个case,并将优先级字段更新为非null。然后您的排序将在每个系统中按预期工作。 (并且你不会接受普遍的SQL烦恼/意外,如NULL传播表达nuking。)