我创建了一个自定义UserModelChoiceField类,该类接受用户的QuerySet并使用其全名填充选择字段:
class UserModelChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return "{} ({})".format(obj.get_full_name(), obj.username)
我现在正试图使用这个类:
calibrated_by_internal = UserModelChoiceField(
queryset=total_qs,
required=False,
widget=forms.Select(attrs={"class": "form-control"})
)
我试图创建一个自定义排序的QuerySet,它允许我在按字母顺序排序的表单上放置User ModelChoice选择字段,但是特定权限组的3个成员放在顶部。
例如:
小组成员: 查理,艾伦,布莱恩
不是小组成员: 本,克里斯,艾丽西亚......等等。
必需的QuerySet /选择字段排序: 艾伦,布莱恩,查理,艾丽西亚,本,克里斯......等等。
鉴于我正在使用Django 1.11,我想我会尝试新的.union ORM功能:
group_members = User.objects.filter(groups__name="AddEditCalibrations").order_by("first_name", "last_name")
everyone_else = User.objects.exclude(username__in="group_members").order_by("first_name", "last_name")
total_qs = group_members.union(everyone_else)
这只会引发错误:
DATABASE ERROR - ORDER BY not allowed in subqueries of compound statements
如果没有2个ORDER_BY,似乎工作正常,但是列表不是按字母顺序排序的,并且该组的成员需要位于选择的顶部(QS中的第一个)只是混合在一起与其他人一起。
所以我尝试了更简单的方法:
total_qs = User.objects.order_by(groups__name="AddEditCalibrations", "first_name", "last_name")
引发错误:
SyntaxError: positional argument follows keyword argument
关注rajkris'建议使用itertools我试过:
total_list = list(chain(group_members, everyone_else))
鉴于我需要一个QS来填充选择字段,然后尝试将其转换回QS:
total_qs = User.objects.filter(username__in=total_list)
但是这只能得到一个未排序的列表,所有用户混合在一起而没有任何排序。
答案 0 :(得分:3)
您无法通过具有该语法的条件进行排序。您可以按Newtonsoft.Json
订购,但这不是您想要的。相反,您需要将其翻译成另一个可以订购的字段 - 让我们将其称为groups__name
; weight
应获得groups__name="AddEditCalibrations"
weight
,其他人的权重应为0
。
你可以试试这个:
1
如果from django.db.models import IntegerField, Value
group_members = User.objects.filter(groups__name="AddEditCalibrations").annotate(weight=Value(0, IntegerField()))
everyone_else = User.objects.exclude(groups__name="AddEditCalibrations").annotate(weight=Value(1, IntegerField()))
total_qs = group_members.union(everyone_else).order_by("weight", "first_name", "last_name")
仍未按预期工作,则可能需要union
。
或者,一气呵成:
all=True
答案 1 :(得分:1)
也许尝试从itertools链转换成一个列表:
from itertools import chain
result_list = list(chain(group_members, everyone_else))
也许我们可以使用这样的东西来获取查询集。
pk_list = [each.id for each in result_list]
ordering = 'FIELD(`id`, %s)' % ','.join(str(id) for id in pk_list)
queryset = User.objects.filter(pk__in=pk_list).extra(
select={'ordering': ordering}, order_by=('ordering',))
答案 2 :(得分:0)
group_members = User.objects.order_by("first_name", "last_name")
sorted_group_members = sorted(group_members.all(), reverse=True, key = lambda a: a.some_function_returning_the_user_group_of_each_user())