Set Django IntegerField by choices=… name

后端 未结 10 880
南笙
南笙 2020-12-07 09:40

When you have a model field with a choices option you tend to have some magic values associated with human readable names. Is there in Django a convenient way to set these f

10条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-07 10:06

    Originally I used a modified version of @Allan's answer:

    from enum import IntEnum, EnumMeta
    
    class IntegerChoiceField(models.IntegerField):
        def __init__(self, choices, **kwargs):
            if hasattr(choices, '__iter__') and isinstance(choices, EnumMeta):
                choices = list(zip(range(1, len(choices) + 1), [member.name for member in list(choices)]))
    
            kwargs['choices'] = choices
            super(models.IntegerField, self).__init__(**kwargs)
    
        def to_python(self, value):
            return self.choices(value)
    
        def get_db_prep_value(self, choice):
            return self.choices[choice]
    
    models.IntegerChoiceField = IntegerChoiceField
    
    GEAR = IntEnum('GEAR', 'HEAD BODY FEET HANDS SHIELD NECK UNKNOWN')
    
    class Gear(Item, models.Model):
        # Safe to assume last element is largest value member of an enum?
        #type = models.IntegerChoiceField(GEAR, default=list(GEAR)[-1].name)
        largest_member = GEAR(max([member.value for member in list(GEAR)]))
        type = models.IntegerChoiceField(GEAR, default=largest_member)
    
        def __init__(self, *args, **kwargs):
            super(Gear, self).__init__(*args, **kwargs)
    
            for member in GEAR:
                setattr(self, member.name, member.value)
    
    print(Gear().HEAD, (Gear().HEAD == GEAR.HEAD.value))
    

    Simplified with the django-enumfields package package which I now use:

    from enumfields import EnumIntegerField, IntEnum
    
    GEAR = IntEnum('GEAR', 'HEAD BODY FEET HANDS SHIELD NECK UNKNOWN')
    
    class Gear(Item, models.Model):
        # Safe to assume last element is largest value member of an enum?
        type = EnumIntegerField(GEAR, default=list(GEAR)[-1])
        #largest_member = GEAR(max([member.value for member in list(GEAR)]))
        #type = EnumIntegerField(GEAR, default=largest_member)
    
        def __init__(self, *args, **kwargs):
            super(Gear, self).__init__(*args, **kwargs)
    
            for member in GEAR:
                setattr(self, member.name, member.value)
    

提交回复
热议问题