【问题标题】:Django: field's default value from self model's instancesDjango:来自自我模型实例的字段默认值
【发布时间】:2011-04-04 04:22:41
【问题描述】:

如何从模型的现有对象中获取字段的默认值?

我尝试了这些,但没有成功:

1)

class ModelA(models.Model):
    fieldA = models.CharField(default=self.get_previous())

    def get_previous(self):
        return ModelA.objects.all()[0].fieldA

NameError: name 'self' is not defined

2)

class ModelA(models.Model):
    fieldA = models.CharField(default=ModelA.get_previous())

    @staticmethod
    def get_previous():
        return ModelA.objects.all()[0].fieldA

NameError: name 'ModelA' is not defined

3)

class ModelA(models.Model):
    fieldA = models.CharField(default=get_previous())

def get_previous():
    return ModelA.objects.all()[0].fieldA

NameError: global name 'get_previous' is not defined

4)

def get_previous():
    return ModelA.objects.all()[0].fieldA

class ModelA(models.Model):
    fieldA = models.CharField(default=get_previous())

NameError: global name 'ModelA' is not defined

我很清楚为什么 3) 和 4) 不起作用。 我可以想象为什么 1) 不起作用 - 看起来类的属性不能引用实例的(即自我)。 我可以想象为什么 2) 不起作用 - 显然在解释器将通过整个课程之前没有对 ModelA 的引用。

那么我应该如何处理呢?

【问题讨论】:

    标签: django default field


    【解决方案1】:

    在您的示例中,您需要删除呼叫操作员()

    目前该语句在第一个读取解析周期立即执行。通过指定符号名称,Django 类接收一个函数指针,当它实际需要默认值时将执行该指针。

    例子变成:

    def get_previous():
        return ModelA.objects.all()[0].fieldA
    
    class ModelA(models.Model):
        fieldA = models.CharField(default=get_previous)
    

    如果您要对很多字段执行此操作,请考虑覆盖 save 函数,这样您只需从数据库中获取前一个对象一次。

    【讨论】:

    • 好点!就我而言,虽然我有很多字段要获取默认值,所以我需要为每个字段设置单独的函数。 (但我会考虑使用 lambda 来概括这一点,比如 lambda: get_default('field_name')
    • 等价的,你应该可以做到default=lambda: ModelA.objects.all()[0].fieldA
    • 请注意,默认使用 lambda 函数会干扰迁移,因为 lambda 函数无法序列化。
    【解决方案2】:

    如果您只想输出默认值,请像这样覆盖__getattr__() 方法:

    class ModelA(models.Model):
      # your fields
      def __getattr__(self, name):
        if(name == 'fieldA' and !self.fieldA):
          return self.get_previous()
        else:
          return super(ModelA, self).__getattr__(name)
    

    从对象中保存默认值会稍微困难一些。我想到的第一个解决方案,override save() method(我相信有更简单的解决方案)

    【讨论】:

      【解决方案3】:

      选项 1:Use model forms。这些是基于模型的表单,您可以使用来自特定实例的值轻松填充它们的值。如果您希望将默认值作为在表单中显示给用户的内容,则此选项非常好,显然。

      选项 2:Override the model's save method,并在那里对检查进行编码 - 如果 fieldA 为 None,则在其中输入一些值。如果您希望默认值在数据层起作用,而不仅仅是作为表单默认值(即,也适用于您以其他方式创建的实例),则此选项会更好。

      【讨论】:

      • 我的意思是向用户显示默认值,如果没有值则不保存它,因此您的答案的 Option_1 看起来不错。虽然我更喜欢 vdboor 的答案,因为它是 python 级别的,而不是 django 特定的。 Djangonauts,如果我走错路,请纠正我;-)
      猜你喜欢
      • 1970-01-01
      • 2012-12-16
      • 1970-01-01
      • 1970-01-01
      • 2010-10-19
      • 2017-01-28
      • 2022-01-15
      • 1970-01-01
      相关资源
      最近更新 更多