class 模型选择
class for model choices
如何使用 class 在 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))
主要问题是您正在尝试初始化 class 实例之外的内容,因此您可以
field = models.CharField(choices=ChoicesCls().get_choices())
但这仍然不是很有用(在我看来)
我发现最好从模块中导入元组列表并将其用作选择,不需要为此生成 class。
这有一个额外的好处,它允许你做你想做的第二件事,因为你也在模块级别定义了选项
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)]
尝试这样的事情
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 class。你应该可以做到
option = "ONE"
getattr(TestModel._meta.get_field('field').choices, "OPTION_{}_SHORT".format(option))
要扩展 ,您可以创建自定义字段:
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()
一样使用 my_model_instance.get_field_display_short()
。
如何使用 class 在 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))
主要问题是您正在尝试初始化 class 实例之外的内容,因此您可以
field = models.CharField(choices=ChoicesCls().get_choices())
但这仍然不是很有用(在我看来)
我发现最好从模块中导入元组列表并将其用作选择,不需要为此生成 class。
这有一个额外的好处,它允许你做你想做的第二件事,因为你也在模块级别定义了选项
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)]
尝试这样的事情
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 class。你应该可以做到
option = "ONE" getattr(TestModel._meta.get_field('field').choices, "OPTION_{}_SHORT".format(option))
要扩展
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()
一样使用 my_model_instance.get_field_display_short()
。