【问题标题】:Dynamic default value of model field based on another field基于另一个字段的模型字段的动态默认值
【发布时间】:2016-04-19 20:45:53
【问题描述】:

我想在现有模型中添加一个新字段,并将默认值作为模型中已存在的字段。

现有模型(仅举例)

class Product(models.Model)
    name = models.CharField(max_length=127)

修改后的模型

class Product(models.Model):
    name = models.CharField(max_length=127)
    full_name = models.CharField(max_length=127)

我在这里添加新字段 full_name 并希望所有现有字段的值与 name 字段相同。 经过一些解决方案后,我知道我们可以定义和调用具有默认属性的方法,如下所示:

class Product(models.Model):

    def get_name(self):
        return self.name

    name = models.CharField(max_length=127)
    full_name = models.CharField(max_length=127, default=get_name)

但这会报错:

ValueError: Could not find function dt_default in cater.models.
Please note that due to Python 2 limitations, you cannot serialize unbound method functions (e.g. a method declared and used in the same class body). Please move the function into the main module body to use migrations.
For more information, see https://docs.djangoproject.com/en/1.8/topics/migrations/#serializing-values

然后我在类之外定义了这个方法,但是我无法访问self.name,因为那时我无权访问类实例。

任何人都可以请同样帮助我,将不胜感激。

【问题讨论】:

    标签: python-2.7 django-models django-orm


    【解决方案1】:

    您拥有的代码将导致数据库表中的两列内容相同,这看起来像是不必要的重复。所以第一个问题是你为什么需要这个?

    如果你只是为了显示需要这个,你可以在模型类中定义一个方法或一个属性,而不是添加一个字段,即:

    class Product(models.Model):
    
        @property
        def full_name(self):
            return self.name
    
        name = models.CharField(max_length=127)
    

    这样在 DB 中您将只有 name,但您将能够访问 Product 实例上的 full_name 属性:

    p = Product(name='Pr1')

    p.name 会得到你"Pr1"

    p.full_name 会得到你"Pr1"

    如果您这样做是为了将来删除name 字段,然后只使用full_name,那么我建议您改为查看migrations

    您还可以在模型上重新定义save() 方法并在调用超类save() 之前在那里进行默认分配。

    附:如果您刚刚开始,那么从 Python 2.7 迁移到 3.5 并使用最新的语言功能编写您的项目并不是一个坏主意。

    另请参阅https://docs.djangoproject.com/en/1.9/topics/migrations/#migration-serializing,了解 Python 2 和 Python 3 中的方法序列化问题。基本上更新到 Python 3 可能会使您的代码正常工作。

    【讨论】:

    • 其实上面的例子只是为了解释。您可以假设它就像我在表中有两列分别命名为 amount 1amount 2 并且我需要在表中添加名为 total_amount 的第三列,默认值是每一行中两列的总和.
    • 您确定需要这个吗?这不是最好的数据库设计决策,除非您绝对确定需要它来提高性能。当您可以使用内置 SQL 函数在 DB 中计算总和时,存储总和是多余的。而在 Django 中,在进行查询时,如果需要此 total_amount,您可以使用 annotateSum 将其添加到 QuerySet 中带有 amount_1amount_2 的每个对象中,并将在 DB 中计算,不在 Python 中,所以它会比较快。但是,如果您需要保留它 - 一种方法是像您一样使用该功能,但切换到 Python 3,这样它就可以工作了。
    • 另一种方法是在您的模型中重新定义save(),尽管有一些缺点,例如在某些情况下不会调用save,尽管在这种情况下也可能不会调用您的函数,请参阅 Django 文档以了解更多信息。
    • 我知道注释和聚合,我刚刚给你一个例子来解释我的问题,我知道我们可以在 python 3 中做同样的事情,但需要 python 2.7 的解决方案。跨度>
    • 我明白了,我只是给你我的建议。无论如何,在你的情况下,IMO 看看在模型 docs.djangoproject.com/en/1.9/topics/db/models/… 上重新定义 save() 方法@
    猜你喜欢
    • 2015-09-26
    • 2016-01-02
    • 2011-05-21
    • 1970-01-01
    • 2016-05-30
    • 1970-01-01
    • 1970-01-01
    • 2019-07-17
    • 1970-01-01
    相关资源
    最近更新 更多