Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 自动为Django模型中的每个选项添加常量_Python_Django_Django Models - Fatal编程技术网

Python 自动为Django模型中的每个选项添加常量

Python 自动为Django模型中的每个选项添加常量,python,django,django-models,Python,Django,Django Models,在Django中,我经常使用以下模式: class MyModel(models.Model): FOO = 1 BAR = 2 GOO = 3 BLAH_TYPES = ( (FOO, 'Foodally boogaly'), (BAR, 'Bar bar bar bar'), (GOO, 'Goo goo gaa gaa'), ) TYPE_FOR_ID = dict(BLAH_TYPES)

在Django中,我经常使用以下模式:

class MyModel(models.Model):

    FOO = 1
    BAR = 2
    GOO = 3

    BLAH_TYPES = (
        (FOO, 'Foodally boogaly'),
        (BAR, 'Bar bar bar bar'),
        (GOO, 'Goo goo gaa gaa'),
    )

    TYPE_FOR_ID = dict(BLAH_TYPES)

    ID_FOR_TYPE = dict(zip(TYPE_FOR_ID.values(), TYPE_FOR_ID.keys()))

    blah = models.IntegerField(choices=BLAH_TYPES)

是否有一种其他人遵循的好模式可以实现相同的效果(即,我可以访问具有名称的常量和双向的字典)?

这是初始化常量的最简洁的方法:

# foobar choices constants
FOO, BAR, BAZ = range(3) 

# bebop choices constants (if you prefer this to readability)
(BUU,
BAA,
DII,
DUU) = range(4)

# then, in a galaxy far away, much to your expectations:
>> FOO
0
>> DII
2
在任何情况下,我通常会创建一个
const.py
,并将所有的疯狂都保留在那里(只看一个98行长的),但一定要将它们移出模型类,并将它们作为模块数据的一部分,以节省时间和内存,除非您做一些动态的事情


否则,你就要尽可能地做好这件事。我还做了一个
BLAH_TYPES
,以符合每个开发人员都习惯于阅读的Django choices结构。这是你无法避免的,也无法走捷径的一部分。如果我需要这些转换,比如
ID\u FOR_TYPE
,我只需在选项下面定义它们。可读、干净、紧凑。

卡尔·迈耶的图书馆有一个很好的解决方案——选择类,它允许您声明一个通过人类可读属性访问的选择列表。

我也有同样的渴望,这就是我写的:

from django.db import models
from django.db.models.base import ModelBase
import re

class ModelBaseWithChoices(ModelBase):
    def __new__(cls, name, bases, attrs):
        def format_label(label):
            return re.sub('[^A-Z]+', '_', label.upper()).strip('_')

        def get_choices(attrs):
            for attr, value in attrs.items():
                if attr.endswith('_CHOICES') and isinstance(value, tuple):
                    base = '_'.join(attr.split('_')[:-1])
                    for val, label in value:
                        yield '_'.join((base, format_label(label))), val

        attrs.update(list(get_choices(attrs)))
        return super(ModelBaseWithChoices, cls).__new__(cls, name, bases, attrs)

class ModelWithChoices(models.Model):
    __metaclass__ = ModelBaseWithChoices

    class Meta:
        abstract = True
从那里,您可以将
MyModel
改写为:

class MyModel(ModelWithChoices):
    BLAH_CHOICES = ((1, 'Foodally boogaly'),
                    (2, 'Bar bar bar bar'),
                    (3, 'Goo goo gaa gaa'))

    blah = models.IntegerField(choices = BLAH_CHOICES)
并在模型中自动为您创建所有常量。从Django shell:

>>> MyModel.BLAH_FOODALLY_BOOGALY
1
>>> MyModel.BLAH_GOO_GOO_GAA_GAA
3