白日依山尽,黄河入海流。欲穷千里目,更上一层楼。 -- 唐·王之涣

Django model中choice的使用

美图欣赏-大鹏展翅


Django model choice

Django model中的choice使用核心是利用二元组 , 二元组的第一个元素实际model存储的值,第二个元素是用户友好阅读的值

常规用法

单独定义一个二元组

1
2
3
4
5
LANGUAGE_V1 = [
('cn', 'Chinese'),
('en', 'English'),
('fr', 'French'),
]

然后在Django model中使用

1
2
3
4
5
6
7
8
9
from django.db import models


class Book(models.Model):
name = models.CharField(max_length=128)
language = models.CharField(max_length=2, choices=LANGUAGE_V1)

def __str__(self):
return self.name

作为Model类型的常量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Book(models.Model):

CHINESE = 'cn'
ENGLISH = 'en'
FRENCH = 'fr'

LANGUAGE_V2 = (
(CHINESE, 'Chinese'),
(ENGLISH, 'English'),
(FRENCH, 'French')
)

name = models.CharField(max_length=128)
language = models.CharField(max_length=2, choices=LANGUAGE_V2, default=CHINESE)

def __str__(self):
return self.name

官方建议的枚举类型

1
2
3
4
5
6
7
8
9
10
11
12
13
class Book(models.Model):

class LanguageV3(models.TextChoices):
CHINESE = 'cn', 'Chinese'
ENGLISH = 'en', 'English'
FRENCH = 'fr', 'French'

name = models.CharField(max_length=128)
# 注意这里的choices值的用法 LanguageV3.choices
language = models.CharField(max_length=2, choices=LanguageV3.choices, default=LanguageV3.CHINESE)

def __str__(self):
return self.name

除了 TextChoices, 还有 models.IntegerChoicesmodels.Choices

Python的Enum类实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from enum import Enum, EnumMeta

class LangaugeEnum(Enum):
ch = 'Chinese'
en = 'English'
fr = 'French'

class Book(models.Model):
name = models.CharField(max_length=128)
# 注意这里的choices值的用法, 使用了 列表表达式
# 和 default的赋值 LangaugeEnum.cn.name
language = models.CharField(max_length=2, choices=[(tag.name, tag.value for tag in LangaugeEnum)], default=LangaugeEnum.ch.name)

def __str__(self):
return self.name

其实Python的Enum类实现更推荐如下方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class ChoiceEnumMeta(EnumMeta):
def __iter__(self):
return ( (tag.name, tag.value) for tag in super().__iter__())


class ChoiceEnum(Enum, metaclass=ChoiceEnumMeta):
pass


class LangaugeEnum(ChoiceEnum):
ch = 'Chinese'
en = 'English'
fr = 'French'

class Book(models.Model):
name = models.CharField(max_length=128)
# 注意这里的choices值的用法: LangaugeEnum
# 和 default的赋值 LangaugeEnum.cn.name
language = models.CharField(max_length=2, choices=LangaugeEnum, default=LangaugeEnum.ch.name)

def __str__(self):
return self.name

不同的方式最终入库的结果和admin后台的用法是一样的

1
2
3
4
5
6
7
8
9
sqlite> select * from app_book ;
1|Python Book Examples|ch
sqlite> select * from app_bookv2;
1|资治通鉴|ch
sqlite> .schema app_book
CREATE TABLE IF NOT EXISTS "app_book" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(128) NOT NULL, "language" varchar(2) NOT NULL);
sqlite> .schema app_bookv2
CREATE TABLE IF NOT EXISTS "app_bookv2" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(128) NOT NULL, "language" varchar(2) NOT NULL);
sqlite>

admin 后台使用

django-model-choice-enum

参考

关于django model fields中的choice用法

参考: Enumeration types

作者

Colin

发布于

2022-08-25

许可协议