Django 南元';t迁移我的自定义字段

Django 南元';t迁移我的自定义字段,django,django-models,python-2.7,django-south,django-1.3,Django,Django Models,Python 2.7,Django South,Django 1.3,我有一个模型,它本身有一个可为空的外键关系(这个“self”可以是任何有这个外键的模型)。此外键是防止循环关系的自定义类 在\uuuu init\uuuu中对super()的调用包含null=True和blank=True,因此需要包含在南方的检验规则中。这至少使schemamigration工作,但迁移仍然失败 以下代码显示:自定义外键、检查规则和使用外键的模型 # Foreign key class ParentField(models.ForeignKey) def __init_

我有一个模型,它本身有一个可为空的外键关系(这个“self”可以是任何有这个外键的模型)。此外键是防止循环关系的自定义类

\uuuu init\uuuu
中对
super()
的调用包含
null=True
blank=True
,因此需要包含在南方的检验规则中。这至少使schemamigration工作,但迁移仍然失败

以下代码显示:自定义外键、检查规则和使用外键的模型

# 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'}],

有谁能告诉我我做错了什么,或者有什么建议可以解决这个问题吗?

最终这个解决方案对我有效,感谢谷歌集团的Shai:

South在尝试构建自定义字段的实例时,收集(使用 规则)类中不同KWARG的值。其中之一就是
“到”
参数;您可以在迁移代码中看到它的指定

然后,它获取收集到的值并将其传递给构造函数。所以 实际上,你接到了电话

fields.ParentField(related_name='set', to=orm['module.ModelClass'])
但是,在
\uuuu init\uuuu
中,这会被转换为

models.ForeignKey('self', related_name='set', to=orm['module.ModelClass'])
因此,
'to'
参数有两个值——第一个是位置参数
“自我”

至少有一个解决方案,就是对null和 空白参数——将其添加到kwargs中,而不是直接添加到调用中

kwargs.setdefault('to', 'self') 

我有类似的问题,但通过调用:
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