常量的Django模型字段?

时间:2017-09-05 11:03:07

标签: python django python-3.x architecture

如何在常量中定义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)我们将这些字段用于管理门户网站或任何其他地方。)

2 个答案:

答案 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)

我认为以下信息可能有益:

要实现这一点,首先需要考虑如何从字符串定义类参数。因此,我遇到了一种从基类动态创建派生类的方法: link

特别是 this 回答是我正在寻找的。您可以使用type()命令动态创建类。

从这里开始,搜索如何将其与Django集成。不出所料,有人已经尝试过 - here

在其中一个 answers 中,他们提到了动态Django模型。我没有尝试过,但它可能就是你在寻找的东西。