You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Django ORM中如何直接获取字段选项对应值而非存储值?

在Django ORM中直接获取字段选项显示值的方法

当然可以!在Django里,针对带choices的字段,有好几种实用的方法能让你直接从QuerySet里拿到对应的显示值,不用自己手动写映射逻辑。我给你整理几个常用的方案,按需选择:

1. 用Django自带的get_<field>_display()方法

这是最基础也最常用的方式——每个定义了choices的字段,Django都会自动给模型实例生成一个get_<field>_display()方法。举个例子:

假设你的模型是这样的:

class Device(models.Model):
    PORT_CHOICES = [
        (1, 'HTTP端口'),
        (2, 'HTTPS端口'),
        (3, 'SSH端口'),
    ]
    port = models.IntegerField(choices=PORT_CHOICES)

查询后,每个实例都能直接调用这个方法拿到显示值:

devices = Device.objects.all()
for device in devices:
    print(device.get_port_display())  # 输出对应的端口名称,比如"HTTP端口"

不过要注意,这是实例方法,QuerySet本身不会把这个值作为字段包含进去,需要你逐个访问实例的方法。如果想让QuerySet的每个对象都自带这个属性,可以往下看其他方案。

2. 用annotate在数据库层面添加显示值字段

如果你希望在查询数据库的时候就直接把显示值算出来,并存为QuerySet的一个字段,可以用Case和When组合annotate实现:

from django.db.models import Case, When, Value, CharField

# 给QuerySet添加port_name字段,直接对应显示值
devices = Device.objects.annotate(
    port_name=Case(
        When(port=1, then=Value('HTTP端口')),
        When(port=2, then=Value('HTTPS端口')),
        When(port=3, then=Value('SSH端口')),
        output_field=CharField(),
    )
)

# 现在直接访问属性即可
for device in devices:
    print(device.port_name)

这个方法的优势是计算逻辑在数据库层面完成,适合需要批量获取显示值、或者要对显示值进行过滤/排序的场景。

3. 自定义模型属性(@property)

如果你觉得调用方法有点麻烦,可以在模型里定义一个@property,把显示值包装成属性:

class Device(models.Model):
    PORT_CHOICES = [
        (1, 'HTTP端口'),
        (2, 'HTTPS端口'),
        (3, 'SSH端口'),
    ]
    port = models.IntegerField(choices=PORT_CHOICES)

    @property
    def port_name(self):
        return self.get_port_display()

这样查询后,直接访问device.port_name就能拿到显示值,写法更简洁,和访问普通模型字段一样。不过这个是在Python层面计算的,和调用方法的性能差不多,适合日常业务代码里使用。

4. 用DRF序列化自动转换(如果做API)

如果你是用Django REST Framework写接口,序列化的时候可以直接让字段自动返回显示值:

from rest_framework import serializers

class DeviceSerializer(serializers.ModelSerializer):
    # 方式1:让port字段直接返回显示值
    port = serializers.ChoiceField(choices=Device.PORT_CHOICES)
    
    # 方式2:单独新增一个字段返回显示值,保留原port字段
    port_name = serializers.CharField(source='get_port_display', read_only=True)

    class Meta:
        model = Device
        fields = ['id', 'port', 'port_name']

序列化后的响应里就会包含对应的端口名称,不用额外处理。


内容的提问来源于stack exchange,提问作者LycuiD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:40:57