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

Posted

技术标签:

【中文标题】使用注释时在 Django 中显示选择字段的名称【英文标题】:Display name of a choice field in Django while using annotate 【发布时间】:2015-06-07 21:00:30 【问题描述】:

我试图在使用注释时获取选项的显示名称,但我无法弄清楚。我有以下查询:

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 (如文档和有关此主题的其他 *** 答案中所述),但 django 抛出错误。即以下似乎不起作用

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

【问题讨论】:

get_prop_display 是属性而不是数据库字段。所以你必须循环它并更新显示值AFAIK。 【参考方案1】:

要在不遍历查询集的情况下完成此操作,您可以使用条件表达式使用显示属性进行注释。注释属性可用于.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()
)

【讨论】:

【参考方案2】:

正如前面所说,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)

【讨论】:

只是 Django 1.10 的小更新:choices = dict(Survey._meta.get_field('what').flatchoices)【参考方案3】:

根据@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 参数传递给 WithChoices,但是,嘿,这可行。

【讨论】:

您好,我一直在使用它,因为它看起来..整洁但是,将它与相关模型一起使用是行不通的,例如: Model1.objects.annotate(f_display=WithChoices(Model1, ' f')) - 好的 Model1.objects.annotate(r_display=WithChoices(Model2, 'r')) - 错误说我的 Model1 有一个指向 model2 的外键字段 .. 并且 model2 有选择...我如何获得这些选择?

以上是关于使用注释时在 Django 中显示选择字段的名称的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 django rest 框架在模板中获取模型选择字段名称而不是 id

表单提交时显示单选按钮选择的名称

在 Django 模板的 Bootstrap 4 多选下拉列表中显示多选字段值

如何在下拉列表中显示所选项目名称?

通过从下拉列表中选择字段名称来显示 mysql 表的字段数据

基于选择的 Django 模板/ChoiceField 显示字段