【问题标题】:South won't migrate my custom fieldSouth 不会迁移我的自定义字段
【发布时间】:2012-10-04 02:23:42
【问题描述】:

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

__init__中对super()的调用包含null=Trueblank=True,因此需要包含在South的检查规则中。这至少使 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'}],

谁能告诉我我做错了什么或任何提示解决这个问题?

【问题讨论】:

    标签: django django-models python-2.7 django-south django-1.3


    【解决方案1】:

    最后这个解决方案对我有用,感谢 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') 
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2012-07-15
        • 2011-10-28
        • 1970-01-01
        • 2017-06-17
        • 2013-07-05
        • 2015-02-03
        • 2013-04-19
        • 2013-08-24
        • 2013-05-13
        相关资源
        最近更新 更多