为什么不能将模型方法作为默认值?Python/Django模型中的self是什么意思?

4

我在理解 self 的行为方面遇到了非常基本的问题。

具体来说,我不明白以下两个代码片段为什么都无法正常工作。第一个片段导致解释器抱怨缺少self作为参数:

self 作为参数缺失

第二个片段则提示:self 不能被引用。

class Model(models.Model)
    name = models.CharField(max_length=200)
    auto_gen_field = models.CharField(max_length=200, default=gen_field())

    def gen_field(self):
        return self.name + 'something'

class Model(models.Model)
    name = models.CharField(max_length=200)
    auto_gen_field = models.CharField(max_length=200, default=gen_field(self))

    def gen_field(self):
        return self.name + 'something'

以下代码也使用了self,并且可以正常工作:
class Model(models.Model)
    name = models.CHarField(max_length=200)
    auto_gen_field = models.CharField(max_length=200, blank=True)

    def gen_field(self):
        return self.name + 'something'

    def save(self):
        self.auto_gen_field = self.gen_field()
        super(Model, self).save(*args, **kwargs)

为什么self引用在一个地方存在而在另一个地方不存在?

我该如何修复前两个代码片段?

2个回答

8
您正在声明字段时调用该方法。此时还没有“self”。
无论如何,您都不想这样做。除了任何self的问题之外,这样做将为默认值返回静态值,因此所有实例都将使用相同的值。这就是为什么重要的原因是传递可调用项:gen_field - 而不是结果 - gen_field()。
(请注意,但仍不起作用:实例不会被传递到函数中,因为它没有被作为实例的方法调用。覆盖保存是正确的方法。)

3

self 是一个惯例(实际上它只是一个像其他名称一样的名称,重要的是它是类方法的第一个参数),它是当前类实例的引用,类似于 C++/Java 中的 this

现在,在

class Model(models.Model)
    name = models.CharField(max_length=200)
    auto_gen_field = models.CharField(max_length=200, default=gen_field())

当评估models.CharField(max_length=200, default=gen_field())时,没有类的实例,因此您不能在其中添加self。这没道理也不可能有道理。
现在,从:https://docs.djangoproject.com/en/1.8/ref/models/fields/#django.db.models.Field.default

Field.default¶

字段的默认值。这可以是一个值或可调用对象。如果是可调用的,它将在每次创建新对象时调用。

默认值不能是可变对象(模型实例、列表、集合等),因为对该对象相同实例的引用将在所有新模型实例中用作默认值。而是将所需的默认值包装在可调用对象中。

你想要传递一个callable,这基本上类似于函数指针将有效的代码如下:
def some_function():
     return something

...

auto_gen_field = models.CharField(max_length=200, default=some_function)

然而,您不能像使用模型方法gen_field()一样将其用作default,因为Django不会将模型实例作为提供的可调用函数的第一个参数传递。

您必须重写save方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接