简体   繁体   English

使用 Django ModelField 选择作为字符串的枚举 — 反模式?

[英]Enum using Django ModelField choices as string — anti-pattern?

I have a Django field that I'm using basically as an enum for notification preferences.我有一个 Django 字段,我基本上将其用作通知首选项的枚举。

Right now I have it set up like so:现在我把它设置成这样:

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)

I know that generally this kind of enum should be set up as a models.IntegerField rather than a CharField , but since the front-end uses Angular and the data is all served via an API, I feel like it might provide a bit more useful information for the front-end to receive 'weekly' rather than 2 , for example.我知道通常这种枚举应该设置为models.IntegerField而不是CharField ,但是由于前端使用 Angular 并且数据都是通过 API 提供的,我觉得它可能会提供一些更有用的例如,前端接收'weekly'而不是2

Is it considered bad practice to use a CharField as an enum?使用CharField作为枚举是否被认为是不好的做法? If so, is my use case small enough that it's not a big deal, or is there something I'm missing that I should change it?如果是这样,我的用例是否足够小以至于没什么大不了的,还是我遗漏了什么我应该改变它?

You might want to consider the Django-model-utils Choices library, which would give you some more control over the text versions of the enum.您可能需要考虑Django-model-utils Choices库,它可以让您更好地控制枚举的文本版本。

To answer your question, not everything lends itself to an integer identifier.为了回答您的问题,并非所有东西都适合整数标识符。 Consider states, Australia has 7 and they have a fixed when known set:考虑州,澳大利亚有 7 个,并且它们有一个固定的已知集:

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

Since these are relatively fixed (the make up of the country is unlikely to change, there is no reason to assign an integer to each, when the textual coding, with the full name works just as well.由于这些是相对固定的(国家的组成不太可能改变,没有理由为每个分配一个整数,当文本编码时,全名也可以。

I wouldn't say that using a CharField as a choice is an anti-pattern, just an approach that should only be applied if you are certain that the abbreviated versions for the database make sense when stored as text.我不会说使用CharField作为选择是一种反模式,只是一种只有在您确定数据库的缩写版本在存储为文本时才有意义时才应该应用的方法。

Also you can use Enum to store your values您也可以使用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])

Is it considered bad practice to use a CharField as an enum?使用 CharField 作为枚举是否被认为是不好的做法? If so, is my use case small enough that it's not a big deal, or is there something I'm missing that I should change it?如果是这样,我的用例是否足够小以至于没什么大不了的,还是我遗漏了什么我应该改变它?

You are looking at this entirely the wrong way.你正在以完全错误的方式看待这个问题。 The choice of field depends entirely on the data you want to store.字段的选择完全取决于您要存储的数据。 So, the question isn't if CharField is bad practice for enum, the question you need to ask is:因此,问题不在于CharField是否是枚举的不良做法,您需要问的问题是:

"What do I need to store in my database for this piece of information?" “对于这条信息,我需要在我的数据库中存储什么?”

There is a school of thought that says that you should only store integers in the database if you want the database to help you do calculations on that field, otherwise, you should store numbers as a string type, because this gives you more flexibility.有一种观点认为,如果您希望数据库帮助您对该字段进行计算,您应该只将整数存储在数据库中,否则,您应该将数字存储为字符串类型,因为这为您提供了更大的灵活性。

I am not going to go much deeper into that because its an opinionated topic, what I am going to say is if you decide that storing the data as characters makes sense for your application, then just do it.我不会更深入地讨论这个问题,因为这是一个固执己见的话题,我要说的是,如果您认为将数据存储为字符对您的应用程序有意义,那么就去做吧。 Do not over cook this in your mind.不要在你的脑海中过度烹饪。

I know that generally this kind of enum should be set up as a models.IntegerField rather than a CharField, but since the front-end uses Angular and the data is all served via an API, I feel like it might provide a bit more useful information for the front-end to receive 'weekly' rather than 2, for example.我知道一般这种枚举应该设置为models.IntegerField而不是CharField,但是由于前端使用Angular并且数据都是通过API提供的,我觉得它可能会提供一些更有用的例如,前端接收“每周”而不是 2 的信息。

I am not sure where you are drawing your conclusions about this, but there is no hard and fast rule about what datatype should enums refer to.我不确定你在哪里得出你的结论,但是没有关于枚举应该引用什么数据类型的硬性规定。 This is up to your application and what information you need to store - and to decide that you need to know how you will query your database for this information.这是到你的应用程序,你需要存储哪些信息-而决定你需要知道你将如何查询数据库,以获得此信息。

In your case, you are looking at this from a API usability perspective, and that is perfectly fine .就您而言,您是从 API 可用性的角度来看这一点的,这很好 Your main purpose of this model is to store information and that information should be stored in a way that provides the most utility to your application.此模型的主要目的是存储信息,并且该信息的存储方式应为您的应用程序提供最大效用。

Finally, do not use ;最后,不要使用; in Python.在 Python 中。 Although technically not incorrect, this is generally frowned upon and does not conform to the python style guide .虽然技术上没有错误,但这通常是不受欢迎的,并且不符合python 风格指南

Using a CharField for an enum is definitely NOT an anti-pattern anymore, considering that the latest Django documentation recommends this approach in its choices example , reprinted here:对枚举使用CharField绝对不再是反模式,考虑到最新的 Django 文档在它的choices示例中推荐了这种方法,重印在这里:

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) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将请求对象发送到Django中的模型方法是否是反模式? - Is it an anti-pattern to send a request object to a model method in Django? Python中的BaseBean反模式 - BaseBean anti-pattern in Python 使用回调满足依赖性的缺点是什么? 而且,这是反模式吗? - What are the drawbacks to using callbacks for satisfying dependencies? And, is this an anti-pattern? 带有上下文管理器的生成器是反模式吗? - Are generators with context managers an anti-pattern? Python 中的嵌套集和字典是反模式吗? - Are nested sets and dictionaries anti-pattern in Python? 除了ManyToMany之外,是否有允许多种选择的Django ModelField? - Is there a Django ModelField that allows for multiple choices, aside from ManyToMany? 如何将 Django Modelfield 选择字符串转换为值 - How to convert Django Modelfield choice string to value 在 `__enter__` 中返回除 `self` 以外的值是一种反模式吗? - Is returning a value other than `self` in `__enter__` an anti-pattern? 向构造函数传递太多参数是否被视为反模式? - Is passing too many arguments to the constructor considered an anti-pattern? Python 装饰器采用附加参数反模式 - Python decorator taking additional argument anti-pattern
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM