在Django模型中定义CharFieldTextField的选择时,我们通常使用元组列表。
然而,从Django 3.0开始引入的TextChoices可以让我们编写更加简洁和有意义的代码


1. 模型选择定义:传统方式

我们常用的方式是如下的元组列表方式。

# models.py
STATUS_CHOICES = [
    ('DF', 'Draft'),
    ('PB', 'Published'),
    ('AR', 'Archived'),
]

class Post(models.Model):
    status = models.CharField(max_length=2, choices=STATUS_CHOICES, default='DF')

传统方式的缺点: - 代码含义难以理解(很难立即知道'DF'代表什么) - 虽然使用了get_FIELD_display(),但未按Enum风格结构化,维护不便 - 在条件比较等方面需要硬编码

if post.status == 'DF':
    ...

2. 通过TextChoices方式的改进


从源代码来看,其原理很简单,想要了解其工作原理的人可以查看Django的源代码。
在这里,我们仅想说明一下使用方法。

# models.py 代码内部
from django.db import models

class PostStatus(models.TextChoices):
    DRAFT = 'DF', 'Draft'
    PUBLISHED = 'PB', 'Published'
    ARCHIVED = 'AR', 'Archived'

class Post(models.Model):
    status = models.CharField(max_length=2, choices=PostStatus.choices, default=PostStatus.DRAFT)

这种方式的优点: - 可以用有意义的名称像PostStatus.DRAFT进行条件处理 - 完美支持get_status_display() - 可以像对象一样处理enum,有利于IDE自动补全和静态分析

if post.status == PostStatus.DRAFT:
    ...
  • 可重用性:如果需要在多个模型中共享相同的选择,可以在外部文件中(choices.py)进行定义

实际上,可重用性是使用TextChoice类的最大优点。
如果Django的多个应用需要共同使用的选择,可以将其放在commons/choices.py等文件中,以便在任何应用中调用选择。


3. 结论


Django的TextChoices是一项出色的功能,帮助我们更直观和坚固地处理模型选择
脱离过去的元组列表方式,提高代码质量吧!