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'
posted @ 2022-11-03 09:41  公众号海哥python  阅读(241)  评论(0编辑  收藏  举报