Вы можете применить это, создав подклассы enum.EnumMeta
:
from enum import EnumMeta, Enum as _Enum
class Enum(_Enum, metaclass=EnumMeta):
def __eq__(self, arg):
if isinstance(arg, self.__class__):
return arg is self
return self.value == arg
Теперь вам никогда не придется звонить enum.value
для сравнение:
class Method(Enum):
GET = 'GET'
POST = 'POST'
>>> get = 'GET'
>>> Method.GET == get
True
>>> get == Method.GET
True
>>> Method.POST == Method.GET
False
Это решает проблему в том смысле, что другие не забудут вызвать .value
для сравнения, но создает большую проблему, потому что теперь экспоненциально более вероятно, что кто-то забудет позвонить .value
при вставке в модель.
Чтобы исправить это, я бы рекомендовал также создать подкласс models.CharField
, чтобы создать собственное поле перечисления:
class EnumField(models.CharField):
def __init__(self, enum, **kwargs):
self.enum = enum
def from_db_value(self, value, expression, connection):
if value is not None:
return self.enum(value)
return None
def to_python(self, value):
if isinstance(value, self.enum):
return value.value
return None
def get_prep_value(self, value):
if isinstance(value, self.enum):
value = value.value
return super().get_prep_value(value)
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
args.append(self.enum)
return name, path, args, kwargs
Теперь вы также можете вставлять в модели без вызова .value
:
class MyModel(models.Model):
method = EnumField(enum=Method)
>>> MyModel.objects.create(method=Method.GET)