Python和Django常量的最佳实践

Dyl*_*ens 39 python django

我有一个依赖于元组的Django模型.我想知道在我的Django程序中引用该元组中的常量的最佳实践是什么.例如,在这里,我想将" default=0" 指定为更具可读性且不需要评论的东西.有什么建议?

Status = (
    (-1, 'Cancelled'),
    (0, 'Requires attention'),
    (1, 'Work in progress'),
    (2, 'Complete'),
)

class Task(models.Model):
    status = models.IntegerField(choices=Status, default=0) # Status is 'Requires attention' (0) by default.
Run Code Online (Sandbox Code Playgroud)

编辑:

如果可能的话,我想完全避免使用一个数字.不知何故,使用字符串'需要注意'将更具可读性.

Ala*_*air 60

定义整数值的常量非常常见,如下所示:

class Task(models.Model):
    CANCELLED = -1
    REQUIRES_ATTENTION = 0
    WORK_IN_PROGRESS = 1
    COMPLETE = 2

    Status = (
        (CANCELLED, 'Cancelled'),
        (REQUIRES_ATTENTION, 'Requires attention'),
        (WORK_IN_PROGRESS, 'Work in progress'),
        (COMPLETE, 'Complete'),
    )

    status = models.IntegerField(choices=Status, default=REQUIRES_ATTENTION)
Run Code Online (Sandbox Code Playgroud)

通过移动常量和Status类内部,您可以保持模块的名称空间更清晰,作为奖励,您可以参考Tasks.COMPLETE导入Tasks模型的任何位置.

  • @Alveoli django的基本模型为模型中的每个字段提供"get_fieldname_display()"函数.因此,get_status_display()已经可用 (3认同)
  • @AnujnI您可能能够以更高效的方式来完成此操作,但我认为这对于该答案的大多数读者来说是过早的优化。 (2认同)

ran*_*lan 16

CANCELED, ATTENTION, WIP, COMPLETE = range(-1, 3)
Status = (
    (CANCELED, 'Cancelled'),
    (ATTENTION, 'Requires attention'),
    (WIP, 'Work in progress'),
    (COMPLETE, 'Complete'),
)

class Task(models.Model):
    status = models.IntegerField(choices=Status, default=CANCELED)
Run Code Online (Sandbox Code Playgroud)


请记住,正如其他人所说,正确的方法是将这些变量放在Model类中.这也是官方django的例子.

只有一个原因是您希望将它放在类命名空间之外,并且只有当这些语义由应用程序的其他模型共享时才会出现.即你无法决定他们属于哪种特定型号.

虽然在您的特定示例中似乎不是这种情况.

  • 赞成,但我更喜欢像 Alasdair 的回答那样将常量移到类中。 (2认同)

Lut*_*elt 12

Python 3.4+: Enum

你写道:"如果可能,我想完全避免使用一个数字." 事实上,一个命名的代表显然更加pythonic.然而,裸字符串易受错别字的影响.

Python的3.4引入了一种称为模块 enum提供EnumIntEnum伪类与此情况有所帮助.有了它,您的示例可以如下工作:

# in Python 3.4 or later:
import enum  

class Status(enum.IntEnum):
    Cancelled = -1,
    Requires_attention = 0,
    Work_in_progress = 1,
    Complete = 2

def choiceadapter(enumtype):
    return ((item.value, item.name.replace('_', ' ')) for item in enumtype)

class Task(models.Model):
    status = models.IntegerField(choices=choiceadapter(Status), 
                                 default=Status.Requires_attention.value)
Run Code Online (Sandbox Code Playgroud)

一旦Django团队回升Enum,它 choiceadapter甚至会被建立在Django中.


Chr*_*ing 7

你可以使用一个namedtuple,使用一个常量似乎适合的永恒.;-)

>>> from collections import namedtuple
>>> Status = namedtuple('Status', ['CANCELLED', 'REQUIRES_ATTENTION', 'WORK_IN_PROGRESS', 'COMPLETE'])(*range(-1, 3))
>>> Status
Status(CANCELLED=-1, REQUIRES_ATTENTION=0, WORK_IN_PROGRESS=1, COMPLETE=2)
>>> Status.CANCELLED
-1
>>> Status[0]
-1
Run Code Online (Sandbox Code Playgroud)

在这种情况下,TaskAlasdair的答案一样使用属性作为常量更有意义,但是命名元组是非常便宜的替代词和不会改变的对象.如果你想在内存中有很多它们,特别方便.它们就像常规元组一样,具有描述性__repr__和属性访问权.

  • 如果你需要进一步[令人信服](http://pyvideo.org/video/367/pycon-2011--fun-with-python--39-s-newer-tools)` [11:35 - 26:00] ` (3认同)