我们正在使用Django 1.4。我们的课程A
有一个与之相关的课程History
。可以有许多与A
的任何单个对象相关的历史记录对象。
History
类有外键到其他类,例如BusinessUnit
。
我想通过 last 历史记录对象对A
的对象进行排序(如果有的话)(按History.logged_at
排序)。
我尝试使用order_by('history__business_unit')
,但它无法正常工作。是否可以使用数据库进行排序,或者我们是否必须使用Python进行排序?如果可能的话,我更喜欢使用数据库进行排序。
答案 0 :(得分:4)
您必须注释最大相关日期,过滤历史对象,其中最大日期等于历史记录的日期,并按business_unit
属性排序。 :
from django.db.models import Max, F
a = A.objects.annotate(last_date=Max('history_set__logged_at'))\
.filter(history_set__logged_at=F('last_date'))\
.order_by('history_set__business_unit__<attribute>')
这样,对于每个A
对象,您可以过滤最后一个History
相关对象,并在关联的business_unit
上进行排序。仅使用history_set__business_unit
将按业务部门的ID排序,因此对于任何有意义的排序,您需要确定要订购的business_unit
的哪个属性。
答案 1 :(得分:0)
最后我用Python排序,使用list.sort:
def human_key(key):
parts = re.split('(\d*\.\d+|\d+)', key.lower())
return tuple((e.swapcase() if i % 2 == 0 else float(e)) for i, e in enumerate(parts))
if (ordered in ["unregistered_business_unit", "unregistered_operational_unit", "unregistered_date"]):
a_list = list(a_list)
for a in a_list:
a_history = list(a.history.all().order_by('-logged_at'))
if (len(a_history) > 0):
a.last_a_history = a_history[0]
else:
a.last_a_history = None
if (ordered == "unregistered_business_unit"):
a_list.sort(key=lambda a: (a.last_a_history.business_unit.description.lower() if ((a.last_a_history) and (a.last_a_history.business_unit)) else None, a.last_a_history.business_unit.identifier if ((a.last_a_history) and (a.last_a_history.business_unit)) else None, human_key(a.last_a_history.operational_unit.identifier) if ((a.last_a_history) and (a.last_a_history.operational_unit)) else None, a.mac_address), reverse=reverse_flag)
elif (ordered == "unregistered_operational_unit"):
a_list.sort(key=lambda a: (human_key(a.last_a_history.operational_unit.identifier) if ((a.last_a_history) and (a.last_a_history.operational_unit)) else None, a.last_a_history.business_unit.description.lower() if ((a.last_a_history) and (a.last_a_history.business_unit)) else None, a.last_a_history.business_unit.identifier if ((a.last_a_history) and (a.last_a_history.business_unit)) else None, a.mac_address), reverse=reverse_flag)
elif (ordered == "unregistered_date"):
a_list.sort(key=lambda a: (a.last_a_history.logged_at if (a.last_a_history) else pytz.utc.localize(datetime(MINYEAR, 1, 1)), a.mac_address), reverse=reverse_flag)