Django中如何同时使用get_FOO_display与values()方法?
Django中获取choices字段可读值并在模板展示的解决方案
问题场景
当前使用values()查询Leave模型时,只能返回type字段的存储值(如'10'、'20'),希望同时获取对应的可读名称(如'Type 1'、'Type 2'),并在模板中展示。
相关代码
models.py
class Leave(CommonFields): LEAVES_TYPES = [ ('10', _('Type 1')), ('20', _('Type 2')), ('30', _('Type 3')), ] owner = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True) type = models.CharField(max_length=3, choices=LEAVES_TYPES, null=True, default="10") def __str__(self): return f"{self.owner.first_name} {self.owner.last_name} : du {self.begin_date.strftime('%d-%m-%Y')} au {self.end_date.strftime('%d-%m-%Y')}"
views.py
def get_queryset(self): return Leave.objects.filter(is_active=True).values('type', 'begin_date','end_date','range','comment','status')
leave_list.html
<td>{{leave.type}}</td>
解决方案
方案一:返回模型实例(最优方案)
放弃使用values(),直接返回模型实例的QuerySet。模型实例自带get_FOO_display()方法,可以直接获取choices字段的可读值,无需额外处理,维护成本最低。
修改views.py的get_queryset方法:
def get_queryset(self): return Leave.objects.filter(is_active=True)
修改模板leave_list.html,调用get_type_display()方法:
<td>{{ leave.get_type_display }}</td>
方案二:使用annotate手动添加可读值(适合必须用values()的场景)
如果业务需求必须使用values()返回字典,可以通过annotate结合Case和When,将可读值手动注入查询结果。但这种方式需要和LEAVES_TYPES同步维护,若选项变更需同时修改代码。
修改views.py:
from django.db.models import Case, When, Value, CharField def get_queryset(self): return Leave.objects.filter(is_active=True).annotate( type_display=Case( When(type='10', then=Value(_('Type 1'))), When(type='20', then=Value(_('Type 2'))), When(type='30', then=Value(_('Type 3'))), output_field=CharField(), ) ).values('type', 'type_display', 'begin_date','end_date','range','comment','status')
修改模板leave_list.html,直接读取注入的type_display字段:
<td>{{ leave.type_display }}</td>
总结
优先选择方案一,这是Django ORM设计的原生用法,代码简洁、易于维护,模板调用也更直观。只有在必须使用字典形式返回数据的场景下,才考虑方案二。
内容的提问来源于stack exchange,提问作者NatNat
相关产品推荐
相关产品推荐

