我正在用models.py中定义的值填充下拉列表,如下所示:
rank_choices = (
('King', 'King')
('Prince', 'Prince')
('Duke', 'Duke')
('Baron', 'Baron')
('Lackey', 'Lackey')
当我在一个特定的时间显示一个有等级的人的列表时,我希望他们出现在降序中。
当前查询(仅按字母顺序):
attendees = Rank.objects.filter(feast__id=feast__id).exclude(rank='Lackey').order_by('rank')
我怎样才能根据它在列表中的位置来改变它的排名呢?
我在考虑这个:
rank_choices = (
(0, 'King')
(1, 'Prince')
(2, 'Duke')
(3, 'Baron')
(4, 'Lackey')
但是,即使我可以从数值中取回冗长的值,排序中的任何更改也会返回数据更改前的不正确值。有更好的办法吗?
选择解
受wim答案的启发,我最后进行了数据迁移,将排名更改为数字值,并按如下方式排序。
ranks = sorted(ranks, key=lambda x: int(x.rank))
通过将模型中的rank_choices导入到我的视图中,并在排序后用相应的标题替换数字值,我将获得详细的值。
发布于 2016-04-18 12:41:07
看起来您将rank
存储在数据库中的CharField中。在不更改模式的情况下执行自定义order_by并不简单。因此,对于简单的情况,可以考虑在python代码中进行排序:
rank_lookup = {rank: n for n,(rank,rank) in enumerate(rank_choices[::-1])}
ranks = Rank.objects.filter(...).values_list('rank', flat=1)
ranks = sorted(ranks, key=rank_lookup.get)
调用sorted
之后,将对queryset进行计算,您将得到一个python列表。
如果这不令人满意,则在Django ORM中可以(但不是很漂亮)通过使用Case
/When
构造在查询集中获得所需的结果:
>>> for rank, rank in rank_choices:
... Rank.objects.create(rank=rank)
...
>>> Rank.objects.order_by('rank') # alphabetical
[<Rank: Baron>, <Rank: Duke>, <Rank: King>, <Rank: Lackey>, <Rank: Prince>]
>>> rank_lookup = {rank: n for n,(rank,rank) in enumerate(rank_choices)}
>>> cases = [When(rank=rank, then=Value(rank_lookup[rank])) for rank in rank_lookup]
>>> cases
[<When: WHEN <Q: (AND: ('rank', 'King'))> THEN Value(0)>,
<When: WHEN <Q: (AND: ('rank', 'Lackey'))> THEN Value(4)>,
<When: WHEN <Q: (AND: ('rank', 'Baron'))> THEN Value(3)>,
<When: WHEN <Q: (AND: ('rank', 'Prince'))> THEN Value(1)>,
<When: WHEN <Q: (AND: ('rank', 'Duke'))> THEN Value(2)>]
>>>
>>> Rank.objects.annotate(my_order=Case(*cases, output_field=IntegerField())).order_by('my_order')
[<Rank: King>, <Rank: Prince>, <Rank: Duke>, <Rank: Baron>, <Rank: Lackey>]
>>> Rank.objects.annotate(my_order=Case(*cases, output_field=IntegerField())).order_by('-my_order')
[<Rank: Lackey>, <Rank: Baron>, <Rank: Duke>, <Rank: Prince>, <Rank: King>]
由于用户"mu太短“在评论中激发了这一想法。这将在Django 1.8+中工作,因为条件表达式中有新的特性。
对于那些不幸被困在较早版本Django上的用户来说,通过构建一个使用Queryset.extra
传递的原始sql片段,同样的想法是可能的。
https://stackoverflow.com/questions/36703590
复制相似问题