django 1.10,py 3.5
这是我的类似Enum的课程:
@deconstructible
class EnumType(object):
@classmethod
def choices(cls):
attrs = [i for i in cls.__dict__.keys() if i[:1] != '_' and i.isupper()]
return tuple((cls.__dict__[attr], cls.__dict__[attr]) for attr in attrs)
def __eq__(self, other):
return self.choices() == other.choices()
以下是该课程的一个例子:
class TransmissionType(EnumType):
TRANSMISSION_PROGRAM = 'TRANSMISSION_PROGRAM'
INFO_PROGRAM = 'INFO_PROGRAM'
SPORT_PROGRAM = 'SPORT_PROGRAM'
以下是我在模特身上使用它的方法:
type = models.TextField(choices=TransmissionType.choices(), db_index=True, default=None)
我认为我根据当前的django deconstruct docs做了一切正确的事情,但显然makemigration脚本仍然会创建每次迁移:
operations = [
migrations.AlterField(
model_name='transmission',
name='type',
field=models.TextField(choices=[('TRANSMISSION_PROGRAM', 'TRANSMISSION_PROGRAM'), ('INFO_PROGRAM', 'INFO_PROGRAM'), ('SPORT_PROGRAM', 'SPORT_PROGRAM')], db_index=True, default=None),
),
]
EDIT1: 预期行为 - 当类成员不更改生成的迁移时,不应包括AlterField
答案 0 :(得分:2)
字典具有任意顺序,因此您的元组也具有任意顺序。特别是在Python 3.3+上,订单可能会改变,因为它使用random hash seed。因此,元组的顺序也是不同的,并且具有相同项但具有不同顺序的元组不相等。 Django检测到此更改并创建新的迁移。
要解决此问题,只需在构造元组之前对键进行排序:
@deconstructible
class EnumType(object):
@classmethod
def choices(cls):
attrs = [i for i in cls.__dict__.keys() if i[:1] != '_' and i.isupper()]
return tuple((cls.__dict__[attr], cls.__dict__[attr]) for attr in sorted(attrs))
def __eq__(self, other):
return self.choices() == other.choices()