关于python:来自常量的Django模型字段?

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字段采用db_column参数来处理这种情况。

在第一个案例中,我不得不说这是一个非常通用的(无论如何都不是新的)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")

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

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

尤其是这个答案是我一直在寻找的。可以使用type()命令动态创建类。

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

在其中一个答案中,他们提到了动态Django模型。我没试过,但可能是你在找的。