带参数和管理页面的构造函数

时间:2014-07-03 13:02:17

标签: django

我有一个包含两个字段的类Foo:整数字段x和逗号分隔的整数字段nn的值表示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而不必将其作为单独的函数编写,以便在创建实例时调用它?

1 个答案:

答案 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正在使用数据库中的Foon值创建x对象,则您不希望设置自己的x值,而是要使用来自数据库的价值。我想你可以查看是否提供了n而不是x,但是如上所述创建自己的“构造函数”类型方法确实更安全,更清晰。