Django模型CharField字段类型定义更为优雅的Choice
官方推荐的一种写法:
class SexType(objects):
MALE = 'M'
FEMALE = 'F'
UNKNOWN = 'N/A'
CHOICES = (
(MALE, '男'),
(FEMALE, '女'),
(UNKNOWN, u'未知'),
)
class User(models.Model):
username = models.CharField(max_length=20, unique=True, verbose_name='名称')
sex = models.CharField(max_length=3, default=SexType.UNKNOWN, choices=SexType.CHOICES, verbose_name='性别')
效果:
数据库存放的值为 ‘M' 'F' 'N/A'
业务逻辑中方便判断:User.objects.filter(sex=SexType.MALE)
序列化器方便返回字段的描述信息(label值):
class UserSerializer(serializers.ModelSerializer):
sex_t = serializers.CharField(source='get_sex_display', read_only=True, required=False)
#source='get_sex_display' 固定写法get_xxx_display
class Meta:
model = User
fields = ('id', 'name', 'sex', 'sex_t')
序列化结果:
[
{"id": 1,
"name": "小明",
"sex": "M",
"sex_t": "男"
},
{"id": 2,
"name": "小王",
"sex": "F",
"sex_t": "女"
}
]
Django3.0以后更建议使用Field.choices枚举类型定义choices选项
from django.db import models
class Status(models.TextChoices):
UNPUBLISHED = 'UN', 'Unpublished'
PUBLISHED = 'PB', 'Published'
class Book(models.Model):
status = models.CharField(
max_length=2,
choices=Status.choices,
default=Status.UNPUBLISHED,
)
class Pamphlet(models.Model):
status = models.CharField(
max_length=2,
choices=Status.choices,
default=Status.PUBLISHED,
)
数据库存储的值为UN、PB
查询时:
unpublished_books = Book.objects.filter(status=Status.UNPUBLISHED)
还可以轻松将值转换为label:
In [2]: book = Book.objects.latest('id')
In [3]: Status(book.status)
Out[3]: <Status.UNPUBLISHED: 'UN'>
In [4]: Status(book.status).label
Out[4]: 'Unpublished'