【问题标题】:Constructors with arguments and the admin page带参数的构造函数和管理页面
【发布时间】:2014-07-03 13:02:16
【问题描述】:

我有一个类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 行,而不必将其编写为单独的函数,以便在创建实例时调用?

【问题讨论】:

标签: django


【解决方案1】:

正如 Germano 在 cmets 中指出的那样,您应该阅读 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 的其他部分(例如管理员)。如果 Django 使用数据库中的 nx 值创建一个 Foo 对象,您不想设置自己的值 x,而是要使用数据库中的值。我想你可以检查一下是否提供了n 而不是x,但是像上面那样创建自己的“构造函数”类型方法确实更安全、更清晰。

【讨论】:

  • 正如 OP 要求 stackoverflow.com/questions/24556655/… 我认为他应该将您的答案标记为已接受。
  • @Germano 他可能在我进行编辑的过程中将其标记为接受。我以为我短暂地看到了一个绿色复选标记。他可能不得不再做一次。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多