我正在尝试使用注释时获取选择的显示名称,但我无法弄清楚。我有以下查询:
Survey.objects.values('what').annotate(count=Count('why')).order_by()
结果是:
[{'count': 34, 'what': u'a'},
{'count': 39, 'what': u'c'},
{'count': 40, 'wat': u'p'}]
但是我想要一些显示选择字段名称而不是密钥的东西:
[{'count': 34, 'what': u'appreciative'},
{'count': 39, 'what': u'creative'},
{'count': 40, 'wat': u'promising'}]
我尝试了get_what_display(如关于此主题的文档和其他stackoverflow答案中所述),但是django会抛出错误。即以下似乎不起作用
Survey.objects.values('get_what_display').annotate(count=Count('why')).order_by()
答案 0 :(得分:3)
如前所述,get_FOO_display
是一种实例方法,而不是.values()
中可以使用的方法。因此,我会用Pythonic的方式来完成你想做的事情:
from django.utils.encoding import force_text
survey_counts = Survey.objects.values('what').annotate(count=Count('why')).order_by()
choices = dict(Survey._meta.get_field_by_name('what')[0].flatchoices)
for entry in survey_counts:
entry['what'] = force_text(choices[entry['what']], strings_only=True)
答案 1 :(得分:1)
基于@bdoubleu的答案,我编写了以下通用条件表达式:
# myapp/utils.py
from django.db.models import Case, CharField, Value, When
class WithChoices(Case):
def __init__(self, model, field, condition=None, then=None, **lookups):
choices = dict(model._meta.get_field(field).flatchoices)
whens = [When(**{field: k, 'then': Value(v)}) for k, v in choices.items()]
return super().__init__(*whens, output_field=CharField())
# example usage
from myapp.utils import WithChoices
from myapp.models import MyModel
MyModel.objects.annotate(what_with_choices=WithChoices(MyModel, 'what')).values('what_with_choices')
可能有一种更清洁的构建方式,不需要将model
arg传递给WithChoices,但是,这可行。
答案 2 :(得分:0)
要在不迭代查询集的情况下完成此操作,可以使用条件表达式对display属性进行注释。带注释的属性可在.values()
中使用。
from django.db.models import Case, CharField, Value, When
choices = dict(Survey._meta.get_field('what')[0].flatchoices)
whens = [When(what=k, then=Value(v)) for k, v in choices.items()]
survey_counts = (
Survey.objects
.annotate(get_what_display=Case(*whens, output_field=CharField()))
.values('get_what_display')
.annotate(count=Count('why'))
.order_by()
)