简体   繁体   English

继承 OneToOneField 会导致 TypeError: __init__() got an unexpected keyword argument 'related_name'

[英]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_nameOneToOneField设置一些常见的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')

Shouldn't it be like this according to doc 1根据 doc 1不应该是这样吗

class MyOneToOneField(models.OneToOneField):
    def __init__(self, to, *args, **kwargs):
        kwargs['related_name'] = 'extra_data'
        kwargs['on_delete'] = models.CASCADE
        super().__init__(to, *args, **kwargs)

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_deleterelated_namekwargs ,但仅限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.

相关问题 类型错误:__init__() 得到了意外的关键字参数“名称”-CONVOKIT - TypeError: __init__() got an unexpected keyword argument 'name' - CONVOKIT TypeError at &#39;&#39; __init__() 得到一个意外的关键字参数 &#39;&#39; - TypeError at '' __init__() got an unexpected keyword argument '' Scrapy错误:TypeError:__ init __()得到一个意外的关键字参数&#39;deny&#39; - Scrapy Error: TypeError: __init__() got an unexpected keyword argument 'deny' TypeError:__init __()得到了意外的关键字参数错误 - TypeError: __init__() got an unexpected keyword argument error TypeError:__ init __()在argparse中有一个意外的关键字参数&#39;type&#39; - TypeError: __init__() got an unexpected keyword argument 'type' in argparse 图片/创建时发生TypeError-__init __()得到了意外的关键字参数&#39;save&#39; - TypeError at images/create - __init__() got an unexpected keyword argument 'save' TypeError:__init __()获得了意外的关键字参数&#39;n_components&#39; - TypeError: __init__() got an unexpected keyword argument 'n_components' TypeError:__init __()获得了意外的关键字参数&#39;cv&#39; - TypeError: __init__() got an unexpected keyword argument 'cv' TypeError:__ init __()得到一个意外的关键字参数&#39;delay&#39; - TypeError:__init__() got an unexpected keyword argument 'delay' TypeError:__ init __()得到一个意外的关键字参数&#39;log_dir&#39; - TypeError: __init__() got an unexpected keyword argument 'log_dir'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM