[英]Inheriting OneToOneField results in TypeError: __init__() got an unexpected keyword argument 'related_name'
I'm using Django 2.2, Python 3.7 and my attempt was to set up some common kwargs (say, on_delete
and related_name
) to the OneToOneField
, by a sub class like the following我正在使用 Django 2.2、Python 3.7,我的尝试是通过子
related_name
为OneToOneField
设置一些常见的kwargs (比如on_delete
和 related_name ),如下所示
class MyOneToOneField(models.OneToOneField):
def __init__(self, to):
super().__init__(to, on_delete=models.CASCADE, related_name='extra_data')
And the model class is like而 model class 就像
class UserExtraData(models.Model):
entity = MyOneToOneField(USER_MODEL)
However, when running makemigrations , it results in:但是,当运行makemigrations时,它会导致:
TypeError: Couldn't reconstruct field entity on UserExtraData: init () got an unexpected keyword argument 'related_name'
TypeError:无法在 UserExtraData 上重建字段实体: init () 获得了意外的关键字参数“related_name”
(I tried removing all other fields, so I am pretty sure this is the field that caused the issue). (我尝试删除所有其他字段,所以我很确定这是导致问题的字段)。
How can I fix this?我怎样才能解决这个问题?
To fix this type of problem, you can change your project settings file.要解决此类问题,您可以更改项目设置文件。 In the settings file, after
INSTALLEDD_APPS
:在设置文件中,在
INSTALLEDD_APPS
之后:
AUTH_USER_MODEL= '<your app name>.<class name>'
if you tend to specify the related_name
in MyOneToOneField
not to use a arg passed to it.如果您倾向于在
related_name
中指定MyOneToOneField
以不使用传递给它的参数。 I prefer我更喜欢
class UserExtraData(models.Model):
entity = models.OneToOneField(USER_MODEL, on_delete=models.CASCADE, related_name='extra_data')
or you could try:或者你可以尝试:
class MyOneToOneField(models.OneToOneField):
def __init__(self, to, *args, **kwargs):
super().__init__(to, *args, **kwargs)
# do others
class UserExtraData(models.Model):
entity = MyOneToOneField(USER_MODEL, on_delete=models.CASCADE, related_name='extra_data')
Found out it was because Django was going to clone
the field for some reason, after digging a little to Django's suggested by the exception traceback:发现这是因为 Django 出于某种原因要
clone
该字段,在对异常回溯所建议的 Django 进行了一些挖掘之后:
File ".../django/db/migrations/state.py", line 414, in from_model
fields.append((name, field.clone()))
File ".../django/db/models/fields/__init__.py", line 493, in clone
return self.__class__(*args, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'related_name'
So take a look at Field.clone
, whose source is所以看看
Field.clone
,它的来源是
def clone(self):
"""
Uses deconstruct() to clone a new copy of this Field.
Will not preserve any class attachments/attribute names.
"""
name, path, args, kwargs = self.deconstruct()
return self.__class__(*args, **kwargs)
apparently the TypeError
is due to kwargs
contains related_name
and on_delete
, which is returned from deconstruct
.显然
TypeError
是由于kwargs
包含相关名称和related_name
,这是从on_delete
返回deconstruct
。
Then, the docstring of deconstruct
says it is to "Return enough information to recreate the field as a 4-tuple:", so I guess what I missed is that I should have overridden it to provide a kwargs
that does not contain on_delete
and related_name
, but only to
.然后,
deconstruct
的文档字符串说它是“返回足够的信息以将字段重新创建为 4 元组:”,所以我想我错过的是我应该重写它以提供不包含on_delete
和related_name
的kwargs
,但仅限to
。
So it finally works like this:所以它最终是这样工作的:
class MyOneToOneField(models.OneToOneField):
def __init__(self, to):
super().__init__(to, on_delete=models.CASCADE, related_name='extra_data')
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
return name, path, args, {'to': kwargs['to']}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.