我有一个包含两个字段的类Foo
:整数字段x
和逗号分隔的整数字段n
。 n
的值表示x
中的元素数。当我创建此类的实例时,我想将x
设置为一组n
个零,每个零用逗号分隔。
这是我到目前为止的代码:
class Foo(models.Model):
n = models.IntegerField(default=0)
x = models.CommaSeparatedIntegerField(max_length = 100)
def __init__(self, _n):
super(User, self).__init__()
self.n = _n
self.x = [0,] * _n
这似乎可以很好地构造Foo
的实例。但是,当我以管理员身份登录并点击其中一个Foo
个实例时,它会向我显示错误:__init__() takes exactly 2 arguments (4 given)
我对此的解释是,当我要求查看时,管理员正在尝试创建Foo
的实例,而不提供必要的参数(尽管我不知道4 given
来自何处)。所以我的问题是:我应该如何使用参数编写Python构造函数,以便实例也可以显示在管理页面中?
我能想到的另一个选择是保留默认构造函数,并在创建实例时编写f = Foo(n = 5)
。但是,如何在默认情况下运行行self.x = [0,] * _n
而不必将其作为单独的函数编写,以便在创建实例时调用它?
答案 0 :(得分:2)
正如Germano在评论中指出的那样,你应该阅读documentation on this subject。
您无法真正覆盖__init__
,因为管理员需要某个界面。你有几个选择。在这里,我将根据您的示例调整文档。
添加classmethod
:
class Foo(models.Model):
n = models.IntegerField(default=0)
x = models.CommaSeparatedIntegerField(max_length = 100)
@classmethod
def create(cls, n):
f = cls(n=n)
f.x = # whatever
return f
f = Foo.create(42)
在Foo管理器上使用方法:
class FooManager(models.Manager):
def create_foo(self, n):
f= self.create(n=n)
f.x = # something
return f
class Foo(models.Model):
n = models.IntegerField(default=0)
x = models.CommaSeparatedIntegerField(max_length = 100)
objects = FooManager()
f = Foo.objects.create_foo(42)
你真的不想覆盖__init__
,因为你无法确定你的代码是在调用它,还是Django的其他部分(比如admin)。如果Django正在使用数据库中的Foo
和n
值创建x
对象,则您不希望设置自己的x
值,而是要使用来自数据库的价值。我想你可以查看是否提供了n
而不是x
,但是如上所述创建自己的“构造函数”类型方法确实更安全,更清晰。