Python 使用注释时在Django中显示选项字段的名称

Python 使用注释时在Django中显示选项字段的名称,python,django,django-models,django-forms,django-queryset,Python,Django,Django Models,Django Forms,Django Queryset,我试图在使用annotate时获得选项的显示名称,但我一直无法弄清楚。我有以下疑问: 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, 'wha

我试图在使用annotate时获得选项的显示名称,但我一直无法弄清楚。我有以下疑问:

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'}]
我尝试获取显示的内容(如本主题的文档和其他stackoverflow答案中所述),但django抛出了一个错误。i、 下面的方法似乎不起作用

Survey.objects.values('get_what_display').annotate(count=Count('why')).order_by()

如前所述,
get\u FOO\u 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)

要在不迭代queryset的情况下完成此操作,可以使用条件表达式来使用display属性进行注释。注释属性可在
.values()
中使用


基于@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')

可能有一种更简洁的构建方法,它不需要将
模型
参数传递给WithChoices,但是,嘿,这是可行的。

get\u prop\u display
是一个属性,而不是数据库字段。因此,您必须循环并更新显示值AFAIK。只需对Django 1.10进行小更新:
choices=dict(Survey.\u meta.get.\u field('what').flatchoices)
# 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')