枚举使用Django ModelField选择,如串 - 反模式?

问题描述 投票:4回答:4

我有我使用的基本上是作为通知首枚举Django的领域。

现在,我有它设置,如下所示:

class MyModel(models.Model):
    # ...
    EVERY_TIME = 'every'; WEEKLY = 'weekly'; NEVER = 'never'
    NOTIFICATION_CHOICES = ((EVERY_TIME, "Every time"), (WEEKLY, "Weekly"), (NEVER, "Never"))
    notification_preferences = models.CharField(choices=NOTIFICATION_CHOICES, default=EVERY_TIME, max_length=10)

我知道,通常这种枚举应设置为models.IntegerField而非CharField,但是由于前端使用角度和数据通过API的所有服务,我觉得它可能会提供更多的有用信息前端接收'weekly'而非2,例如。

它是认为是不好的做法是使用CharField作为一个枚举?如果是这样,我的使用情况下足够小,它不是一个大问题,或者是有什么我失踪,我应该改变它呢?

python django enums
4个回答
4
投票

你可能要考虑Django-model-utils Choices库,这将让您欣赏到枚举的文本版本的一些更多的控制。

要回答你的问题,不是一切适合于整数标识符。考虑美国,澳大利亚有7个,他们有一个固定的已知时设置:

ACT - Australian Capital Territory
NSW - New South Wales
NT  - Northern Territory
QLD - Queensland
SA  - South Australia
TAS - Tasmania
VIC - Victoria
WA  - Western Australia

由于这些都是相对固定的(国家的弥补是不可能改变的,没有理由分配给每个整数,当文本编码,用全名的作品一样好。

我不会说,使用CharField作为一种选择是一个反模式,只是如果你确信当作为文本存储的缩写版本数据库意义应该只适用的方法。

你也可以使用Enum来存储你的价值观

from enum import Enum

class Countries(Enum):
   ACT = "Australian Capital Territory"
   NSW = "New South Wales"
   ...

class MyModel(models.Model):
    country = models.CharField(choices=[(tag.name, tag.value) for tag in Countries])

2
投票

它是认为是不好的做法是使用一个CharField作为一个枚举?如果是这样,我的使用情况下足够小,它不是一个大问题,或者是有什么我失踪,我应该改变它呢?

您正在寻找在这个完全错误的方式。场的选择完全取决于你要存储的数据。所以,问题不在于是否CharField是不好的做法,枚举,你需要问的问题是:

“我需要什么在我的数据库来存储这一块的信息?”

有思想的学校是说,如果你希望数据库来帮助你在这一领域做计算,你应该只存储整数在数据库中,否则,您应该号码存储为一个字符串类型,因为这给你更多的灵活性。

我不会去多深入,由于它的自以为是的话题,我今天要说的是,如果你决定了数据存储为字符有意义的应用程序,那么就去做。不要过度在你的心中做饭这一点。

我知道,通常这种枚举应设置为models.IntegerField而不是一个CharField,但是由于前端使用角度和数据通过API的所有服务,我觉得它可能会提供多一点有用为前端信息来接收“每周”,而不是2,例如。

我不知道你在哪里画这个结论的,但是有大约应该枚举参考什么数据类型没有硬性的规定。这是到你的应用程序,你需要存储哪些信息 - 而决定,你需要知道你将如何查询数据库,以获得此信息。

在你的情况,你是从API可用性的角度看这个,这是完全正常的。你的主要这种模式的目的是存储信息和信息应该存储在提供了最实用到应用程序的方式。

最后,在Python不使用;。虽然技术上不是不正确,这通常是令人难以接受的,不符合python style guide


0
投票

使用CharField一个枚举绝对不是一个反模式了,考虑到最新的Django文档建议its choices example这种方法,在这里转载:

FRESHMAN = 'FR'
SOPHOMORE = 'SO'
JUNIOR = 'JR'
SENIOR = 'SR'
YEAR_IN_SCHOOL_CHOICES = (
    (FRESHMAN, 'Freshman'),
    (SOPHOMORE, 'Sophomore'),
    (JUNIOR, 'Junior'),
    (SENIOR, 'Senior'),
)
year_in_school = models.CharField(max_length=2,
                                  choices=YEAR_IN_SCHOOL_CHOICES,
                                  default=FRESHMAN) 

© www.soinside.com 2019 - 2024. All rights reserved.