模型选择类

时间:2016-03-17 16:21:10

标签: python django python-2.7 django-1.8

如何在Django中使用类来选择模型?

这就是我想要的东西:

class ChoicesCls(object):
    def __init__(self):
        self.OPTION_ONE = 'O1'
        self.OPTION_ONE_SHORT = 'Opt 1'
        self.OPTION_ONE_LONG = 'Option 1'
        self.OPTION_TWO = 'O2'
        self.OPTION_TWO_SHORT = 'Opt 2'
        self.OPTION_TWO_LONG = 'Option 2'

    def get_choices(self):
        return (
            (self.OPTION_ONE, self.OPTION_ONE_LONG),
            (self.OPTION_TWO, self.OPTION_TWO_LONG)
        )


class TestModel(models.Model):
    choices_obj = ChoicesCls()
    field = models.CharField(choices=choices_obj.get_choices)

我想要这样的东西的主要原因是在另一个地方,我可以做像

这样的事情
option = "ONE"
getattr(TestModel.choices_obj, "OPTION_{}_SHORT".format(option))

3 个答案:

答案 0 :(得分:2)

尝试这样的事情

class FakeChoices:
    def __init__(self):
        self.OPTION_ONE = 'O1'
        self.OPTION_ONE_SHORT = 'Opt 1'
        self.OPTION_ONE_LONG = 'Option 1'
        self.OPTION_TWO = 'O2'
        self.OPTION_TWO_SHORT = 'Opt 2'
        self.OPTION_TWO_LONG = 'Option 2'

    def __get_tuple(self):
        return (
            (self.OPTION_ONE, self.OPTION_ONE_LONG),
            (self.OPTION_TWO, self.OPTION_TWO_LONG)
        )

    def __getitem__(self, key):
        return self.__get_tuple()[key]

    def __iter__(self):
        return iter(self.__get_tuple())

...

class TestModel(models.Model):
    field = models.CharField(choices=FakeChoices())

正如您可能想象的那样,您可以将各种疯狂的逻辑放入FakeChoices类中。你应该能够做到

option = "ONE"
getattr(TestModel._meta.get_field('field').choices, "OPTION_{}_SHORT".format(option))

答案 1 :(得分:0)

主要问题是您尝试初始化类实例之外的某些内容,以便您可以这样做

field = models.CharField(choices=ChoicesCls().get_choices())

但那仍然不是很有用(在我看来)

我发现从模块中导入元组列表并将其用作选项更好,没有必要为此生成类。

这有一个额外的好处,它允许你做第二件事,因为你在模块级定义选项也

OPTION_ONE_WITH_A_GOOD_NAME = '1'
OPTION_TWO_WITH_A_GOOD_NAME = '2'

MY_GOOD_NAME_CHOICES = [(OPTION_ONE_WITH_A_GOOD_NAME,OPTION_ONE_WITH_A_GOOD_NAME),
                        (OPTION_TWO_WITH_A_GOOD_NAME,OPTION_TWO_WITH_A_GOOD_NAME)]

答案 2 :(得分:0)

要扩展Mad Wombat's answer,您可以创建自定义字段:

class ChoicesCharField(CharField):
    def contribute_to_class(self, cls, name, virtual_only=False):
        super().contribute_to_class(cls, name, virtual_only)

        def get_FOO_display_short(s):
            value = getattr(s, self.name)
            return self.choices.get_short_name(value)
        get_FOO_display_short.__name__ = 'get_{}_display_short'.format(self.name)
        get_FOO_display_short.short_description = self.verbose_name
        get_FOO_display_short.admin_order_field = self.name

        setattr(cls, get_FOO_display_short.__name__, get_FOO_display_short)

这样您就可以像my_model_instance.get_field_display_short()一样使用my_model_instance.get_field_display()