请考虑以下代码:
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的related_name最终成为“MyAppName.MyModelA.modelAField”。
我想过把它作为一个小丑传递:
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!")
但我希望有更好的东西。
感谢。
答案 0 :(得分:2)
使用contribute_to_class
如前所述,在将字段对象分配给类中的变量之前,必须通过调用其__init__
函数来实例化该字段对象。
然而,在构建模型时,Django在名为contribute_to_class
的字段上查找方法。如果它存在,它将被调用如下:
new_field.object.contribute_to_class(ModelClass, field_name)
如果在自定义字段类中重写此方法,则可以在将字段添加到模型的位置执行所需的初始化。
答案 1 :(得分:1)
我不认为这是可能的。 MyManyToManyField对象在被分配给变量之前将被实例化,所以现在要做一些聪明的事情还为时过早。
对于与字段交互的模型,Django的元类中可能存在相同的魔法,有可能劫持这种交互并将逻辑放在那里。但我现在只是在猜测。
答案 2 :(得分:1)
作为一个kwarg传球似乎并不麻烦。
我怀疑Python无法决定实例的名称,因为一个对象可以有很多引用指针。
例如
x = YourClass()
y = x
YourClass'x'或'y'实例的名称是?或者它只是YourClass的一个实例?