如何在常量中定义Django模型字段并在任何地方使用。 例如,如果我有一个类似的模型: -
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
我想要做的是为作者模型中的字段定义常量,并在模型中提供常量而不是字段名称,如: -
KEY_FIRST_NAME = 'first_name'
KEY_LAST_NAME = 'last_name'
KEY_EMAIL = 'email'
作者模型应使用常量而不是精确键,如: -
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的一种方法所建议的那样,将模型字段定义为常量的最佳实践并在其他地方使用它们(除了内部模型,如if)我们将这些字段用于管理门户网站或任何其他地方。)
答案 0 :(得分:3)
简短的回答:你不能用Python做这个时期(实际上我认为你不能用任何语言这样做,但有人肯定会证明我错了xD)。
现在,如果我们回到你真正的“问题” - 如果你的模型的字段名称永远不变,你不必更改客户端代码 - 你首先需要告诉你是否意味着“python属性名称”或“基础数据库字段名称“。
对于第二种情况,数据库字段名称不必与Python属性名称Django models fields take a db_column
argument匹配来处理这种情况。
对于第一种情况,我不得不说它是一种非常通用的(而不是任何新的)API设计问题,通常的答案是“你不应该改变属于公众的名字” API一旦发布“。现在好了,有时你必须这样做。这里最好的解决方案是使用计算属性将旧名称重定向到弃用期间的新名称,并在移植所有客户端代码后将其删除。
您的模型示例,将'first_name'更改为'firstname':
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
如果你有十几个要重命名的字段,你肯定会想要编写一个自定义描述符(=>计算属性)来保持干燥:
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")
答案 1 :(得分:0)