【问题标题】:Django - get a field's name from within its init functionDjango - 从其 init 函数中获取字段的名称
【发布时间】:2012-02-09 21:45:08
【问题描述】:

考虑以下代码:

class MyManyToManyField(models.ManyToManyField):
  def __init__(self,*args,**kwargs):
    field_name = ?!?
    kwargs["related_name"] = "%(app_label)s.%(class)s." + field_name
    super(MetadataManyToManyField,self).__init__(*args,**kwargs)

class MyModelA(models.Model):
  modelAField = MyManyToManyField("MyModelB")

class MyModelB(models.Model):
  pass

有什么方法可以让我从重载的 init 函数中访问字段的名称?我希望 modelAField 的相关名称最终成为“MyAppName.MyModelA.modelAField”。

我考虑过将它作为一个 kwarg 传递:

  modelAField = MyManyToManyField("MyModelB",related_name="modelAField")

然后在init中使用它:

  field_name = kwargs.pop("related_name",None)
  if not field_name:
    raise AttributeError("you have to supply a related name!")

但我希望有更好的东西。

谢谢。

【问题讨论】:

    标签: django django-models


    【解决方案1】:

    使用contribute_to_class

    如前所述,必须先通过调用其__init__ 函数来实例化字段对象,然后才能将其分配给类中的变量。

    然而,在构建模型时,Django 会在名为 contribute_to_class 的字段上查找方法。如果它存在,它将被这样调用:

    new_field.object.contribute_to_class(ModelClass, field_name)
    

    如果您在自定义字段类中覆盖此方法,则可以在将字段添加到模型时执行所需的任何初始化。

    【讨论】:

    • 那只是一罐真棒。喜欢它!
    • 这看起来不错,但是如果contribute_to_class 被调用before __init__(),那么我在其中设置的任何属性是否仍然不可用?我尝试设置 self._fieldName = 传递给contribute_to_class 的field_name 参数。但是当我从 __init__() 访问 self._fieldName 时,它​​始终提供默认值,而不是我在contribute_to_class 中设置的值。
    • 将近一年后,我正在重写这个应用程序,我遇到了同样的问题。事实证明,Ian 是正确的,我只需要通过执行以下操作来修改contribute_to_class 中的“related_name”参数:self.rel.related_name = "some_string" + name
    【解决方案2】:

    我认为这是不可能的。对象 MyManyToManyField 将在分配给变量之前被实例化,所以现在做任何聪明的事情还为时过早。

    对于与字段交互的模型,在 Django 的元类中可能有同样的魔力,它可能会劫持这种交互并将你的逻辑放在那里。但我现在只是推测。

    【讨论】:

    • 是的,我就是这么想的。我现在有一个可行的解决方案,它只是让我烦恼 b/c 它不是很优雅。谢谢。
    【解决方案3】:

    作为 kwarg 传递似乎没有那么麻烦。

    我怀疑 Python 无法确定实例的名称是什么,因为一个对象可以有很多引用指针。

    例如

    x = YourClass()
    y = x
    

    YourClass 实例的名称是“x”还是“y”?或者它只是 YourClass 的一个实例?

    【讨论】:

    • 我同意你的观点。但我认为可能有一些我可以访问的 DjangoForm 特定属性。毕竟,我知道表单类中的字段名称是什么。
    猜你喜欢
    • 2017-10-09
    • 1970-01-01
    • 1970-01-01
    • 2016-03-26
    • 2021-04-11
    • 2020-08-15
    • 2014-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多