Search code examples
pythondjangopython-2.7django-1.8

class for model choices


How can I use a class for choices of a model in Django?

Here is kind of what I want:

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)

The main reason I want something like this is so in another place I can do something like

option = "ONE"
getattr(TestModel.choices_obj, "OPTION_{}_SHORT".format(option))

Solution

  • Try something like this

    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())
    

    As you might imagine you can put all sorts of crazy logic inside FakeChoices class. And you should be able to do

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