我有一个与自身具有可空外键关系的模型(这个'self'可以是任何具有此外键的模型)。此外键是一个自定义类,可防止循环关系。
super()
中对__init__
的调用包含null=True
和blank=True
,因此需要包含在南方的检查规则中。这至少使 schemamigration 工作,但 migrate 仍然失败。
以下代码显示:自定义外键,检查规则和使用外键的模型。
# Foreign key
class ParentField(models.ForeignKey)
def __init__(self, verbose_name=None, **kwargs):
super(ParentField, self).__init__('self', verbose_name=verbose_name, null=True, blank=True, **kwargs)
@staticmethod
def checkcyclic(object, attr):
'''Check for a cyclic relationship'''
pass
# Introspection rules
add_introspection_rules([
(
[ParentField],
[],
{
'null': ['null', {'default': True}],
'blank': ['blank', {'default': True}],
}
)
], ["^test\.models\.fields\.ParentField"])
# Model
class Relation(Model):
parent = ParentField(related_name='child_set')
迁移会出现以下错误:
$ ./manage.py migrate
[..]
super(ParentField, self).__init__('self', verbose_name=verbose_name, null=True, blank=True, **kwargs)
TypeError: __init__() got multiple values for keyword argument 'to'
我已尝试添加如下规则,但这没有改变任何内容。
'to': ['rel.to', {'default': 'test.models.Relation'}],
任何人都可以告诉我,我做错了什么或者解决方案有什么提示吗?
答案 0 :(得分:2)
最后这个解决方案对我有用,在googlegroups上归功于Shai:
South,当它尝试构建自定义字段的实例时,收集(使用
规则)你班级不同kwargs的价值观。其中之一是
"to"
论证;你看到它在迁移代码中指定了。
然后,它获取它收集的值并将它们传递给构造函数。所以, 实际上,你接到了电话
fields.ParentField(related_name='set', to=orm['module.ModelClass'])
然而,在__init__
内,这会转换为
models.ForeignKey('self', related_name='set', to=orm['module.ModelClass'])
因此'to'
参数有两个值 - 第一个是位置
'self'
。
至少,一个解决方案是做我为null和推荐的相同的事情 空白参数 - 将其添加到kwargs中,而不是直接添加到调用中。
kwargs.setdefault('to', 'self')
答案 1 :(得分:0)
我有类似的问题,但通过致电:kwargs.pop('to', None)
解决了这个问题。
然而,出现了下一个错误:
File "/.../django/db/models/fields/related.py", line 973, in resolve_related_fields
to_field = (self.rel.to._meta.pk if to_field_name is None
AttributeError: 'str' object has no attribute '_meta'
这是因为我将模型名称作为字符串而非类实例传递。南方不支持这一点。通过导入模型并使用它而不是字符串来修复。
以下完整的工作示例:
from django.db import models
from django.conf import settings
from django.db.models.loading import get_model
def _get_user_model():
"""Import django.contrib.auth.models.User or other model set in settings.AUTH_USER_MODEL"""
model_name = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')
return get_model(*model_name.split('.', 1))
def _set_default_kwargs(kwargs):
kwargs.setdefault('on_delete', models.SET_NULL)
kwargs.setdefault('blank', True)
kwargs.setdefault('null', True)
kwargs.pop('to', None) # Remove kwargs['to'] parameter set by south migrations
return kwargs
class ForeignKeyWithUser(models.ForeignKey):
def __init__(self, **kwargs):
kwargs = _set_default_kwargs(kwargs)
User = _get_user_model()
return super(ForeignKeyWithUser, self).__init__(User, **kwargs)
try:
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^toolkit\.models\.fields\.ForeignKeyWithUser"])
except ImportError:
pass