Django model fields from constants?
如何在常量中定义django模型字段并在任何地方使用。例如,如果我有这样的模型:
1 2 3 4 | class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField() |
我要做的是为作者模型中的字段定义常量,并在模型中提供常量而不是字段名,例如:
1 2 3 | KEY_FIRST_NAME = 'first_name' KEY_LAST_NAME = 'last_name' KEY_EMAIL = 'email' |
作者模型应该使用常量而不是精确的键,比如:
1 2 3 4 | class Author(models.Model): KEY_FIRST_NAME = models.CharField(max_length=30) KEY_LAST_NAME = models.CharField(max_length=40) KEY_EMAIL = models.EmailField() |
如何这样做,直接分配给常量在这里不起作用。
我希望将所有字段名存储在常量中,并且在需要的任何地方,我都希望使用常量而不是字符串字段名。
这样做的目的是,如果将来版本中的文件名有任何更改,那么我只想在一个地方进行更改,它应该反映在所有地方。
如果不可能,或者它会使代码变得过于复杂,正如@dirkgroten的一种方法所建议的那样,这比将模型字段定义为常量并在其他地方使用它们(内部模型除外,例如,如果我们将这些字段用于管理门户或任何其他地方)。
简短的回答:在python中不能这样做,period(实际上,我认为您不能用任何语言这样做,但肯定会有人证明我错了xd)。
现在,如果我们回到您真正的"问题"——如果模型的字段名要更改,则不必更改客户机代码——您首先需要知道您的意思是"python属性名"还是"底层数据库字段名"。
对于第二种情况,数据库字段名不必与python属性名匹配,django models字段采用
在第一个案例中,我不得不说这是一个非常通用的(无论如何都不是新的)API设计问题,通常的答案是"一旦发布,就不应该更改作为公共API一部分的名称"。现在嘘!有时你不得不这样做。这里的最佳解决方案是使用计算属性将旧名称重定向到新名称,并在移植了所有客户机代码后将其删除。
您的模型示例,将"名字"更改为"名字":
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class Author(models.Model): # assuming the database column name didn't change # so we can also show how to us `db_column` ;) firstname = models.CharField( max_length=30, db_column='first_name' ) @property def first_name(self): # shoud issue a deprecation warning here return self.firstname @first_name.setter def first_name(self, value): # shoud issue a deprecation warning here self.firstname = value |
如果您有十几个字段要重命名,您肯定希望编写一个自定义描述符(=>计算属性),而不是让它保持干燥:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class Renamed(object): def __init__(self, new_name): self.new_name = new_name def __get__(self, instance, cls): if instance is None: return self # should issue a deprecation warning here return getattr(instance, self.new_name) def __set__(self, instance, value): # should issue a deprecation warning here setattr(instance, self.new_name, value) class Author(models.Model): firstname = models.CharField( max_length=30, db_column='first_name' ) first_name = Renamed("firstname") |
我认为以下信息可能是有益的:
要实现这一点,首先需要考虑如何从字符串定义类参数。因此,我遇到了一种从基类动态创建派生类的方法:链接
尤其是这个答案是我一直在寻找的。可以使用
从这里开始,搜索如何将其与Django集成。不出所料,有人已经尝试过了——在这里。
在其中一个答案中,他们提到了动态Django模型。我没试过,但可能是你在找的。