Django 1.2 +南 0.7 + django-烦人的 AutoOneToOneField 会导致 TypeError: 'LegacyConnection'对象不可迭代

发布于 2024-09-01 06:37:52 字数 2981 浏览 8 评论 0原文

我正在使用 Django 1.2 trunk 和 South 0.7 以及从 django-annoying 复制的 AutoOneToOneField。 South 抱怨该字段没有定义规则,并且新版本的 South 不再具有自动字段类型解析器。因此,我阅读了 South 文档并编写了以下定义(基本上是 OneToOneField 规则的精确副本):

rules = [
  (
    (AutoOneToOneField),
    [],
    {
        "to": ["rel.to", {}],
        "to_field": ["rel.field_name", {"default_attr": "rel.to._meta.pk.name"}],
        "related_name": ["rel.related_name", {"default": None}],
        "db_index": ["db_index", {"default": True}],
    },
  )
]
from south.modelsinspector import add_introspection_rules
add_introspection_rules(rules, ["^myapp"]) 

现在,当我进行架构迁移时,South 会引发以下错误。

Traceback (most recent call last):
  File "manage.py", line 11, in <module>
    execute_manager(settings)
  File "django/core/management/__init__.py", line 438, in execute_manager
    utility.execute()
  File "django/core/management/__init__.py", line 379, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "django/core/management/base.py", line 196, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "django/core/management/base.py", line 223, in execute
    output = self.handle(*args, **options)
  File "South-0.7-py2.6.egg/south/management/commands/schemamigration.py", line 92, in handle
    (k, v) for k, v in freezer.freeze_apps([migrations.app_label()]).items()
  File "South-0.7-py2.6.egg/south/creator/freezer.py", line 33, in freeze_apps
    model_defs[model_key(model)] = prep_for_freeze(model)
  File "South-0.7-py2.6.egg/south/creator/freezer.py", line 65, in prep_for_freeze
    fields = modelsinspector.get_model_fields(model, m2m=True)
  File "South-0.7-py2.6.egg/south/modelsinspector.py", line 322, in get_model_fields
    args, kwargs = introspector(field)
  File "South-0.7-py2.6.egg/south/modelsinspector.py", line 271, in introspector
    arg_defs, kwarg_defs = matching_details(field)
  File "South-0.7-py2.6.egg/south/modelsinspector.py", line 187, in matching_details
    if any([isinstance(field, x) for x in classes]):
TypeError: 'LegacyConnection' object is not iterable

这是否与 Django 1.2 trunk 中最近的更改有关?我该如何解决这个问题?

我按如下方式使用该字段:

class Bar(models.Model):
    foo = AutoOneToOneField("foo.Foo", primary_key=True, related_name="bar")

供参考 django-tagging 中的字段代码:

class AutoSingleRelatedObjectDescriptor(SingleRelatedObjectDescriptor):
    def __get__(self, instance, instance_type=None):
        try:
            return super(AutoSingleRelatedObjectDescriptor, self).__get__(instance, instance_type)
        except self.related.model.DoesNotExist:
            obj = self.related.model(**{self.related.field.name: instance})
            obj.save()
            return obj

class AutoOneToOneField(OneToOneField):
    def contribute_to_related_class(self, cls, related):
        setattr(cls, related.get_accessor_name(), AutoSingleRelatedObjectDescriptor(related))

I'm using Django 1.2 trunk with South 0.7 and an AutoOneToOneField copied from django-annoying. South complained that the field does not have rules defined and the new version of South no longer has an automatic field type parser. So I read the South documentation and wrote the following definition (basically an exact copy of the OneToOneField rules):

rules = [
  (
    (AutoOneToOneField),
    [],
    {
        "to": ["rel.to", {}],
        "to_field": ["rel.field_name", {"default_attr": "rel.to._meta.pk.name"}],
        "related_name": ["rel.related_name", {"default": None}],
        "db_index": ["db_index", {"default": True}],
    },
  )
]
from south.modelsinspector import add_introspection_rules
add_introspection_rules(rules, ["^myapp"]) 

Now South raises the following error when I do a schemamigration.

Traceback (most recent call last):
  File "manage.py", line 11, in <module>
    execute_manager(settings)
  File "django/core/management/__init__.py", line 438, in execute_manager
    utility.execute()
  File "django/core/management/__init__.py", line 379, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "django/core/management/base.py", line 196, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "django/core/management/base.py", line 223, in execute
    output = self.handle(*args, **options)
  File "South-0.7-py2.6.egg/south/management/commands/schemamigration.py", line 92, in handle
    (k, v) for k, v in freezer.freeze_apps([migrations.app_label()]).items()
  File "South-0.7-py2.6.egg/south/creator/freezer.py", line 33, in freeze_apps
    model_defs[model_key(model)] = prep_for_freeze(model)
  File "South-0.7-py2.6.egg/south/creator/freezer.py", line 65, in prep_for_freeze
    fields = modelsinspector.get_model_fields(model, m2m=True)
  File "South-0.7-py2.6.egg/south/modelsinspector.py", line 322, in get_model_fields
    args, kwargs = introspector(field)
  File "South-0.7-py2.6.egg/south/modelsinspector.py", line 271, in introspector
    arg_defs, kwarg_defs = matching_details(field)
  File "South-0.7-py2.6.egg/south/modelsinspector.py", line 187, in matching_details
    if any([isinstance(field, x) for x in classes]):
TypeError: 'LegacyConnection' object is not iterable

Is this related to a recent change in Django 1.2 trunk? How do I fix this?

I use this field as follows:

class Bar(models.Model):
    foo = AutoOneToOneField("foo.Foo", primary_key=True, related_name="bar")

For reference the field code from django-tagging:

class AutoSingleRelatedObjectDescriptor(SingleRelatedObjectDescriptor):
    def __get__(self, instance, instance_type=None):
        try:
            return super(AutoSingleRelatedObjectDescriptor, self).__get__(instance, instance_type)
        except self.related.model.DoesNotExist:
            obj = self.related.model(**{self.related.field.name: instance})
            obj.save()
            return obj

class AutoOneToOneField(OneToOneField):
    def contribute_to_related_class(self, cls, related):
        setattr(cls, related.get_accessor_name(), AutoSingleRelatedObjectDescriptor(related))

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

金橙橙 2024-09-08 06:37:52

尝试将此行更改

(AutoOneToOneField),

为:

(AutoOneToOneField,),

像您一样声明的元组是不可迭代的。

Try to change this line

(AutoOneToOneField),

To this:

(AutoOneToOneField,),

A tuple declared like you did, is not iterable.

淡笑忘祈一世凡恋 2024-09-08 06:37:52

通过删除规则并向 AutoOneToOneField 添加以下方法解决了该问题:

def south_field_triple(self):
    "Returns a suitable description of this field for South."
    from south.modelsinspector import introspector
    field_class = OneToOneField.__module__ + "." + OneToOneField.__name__
    args, kwargs = introspector(self)
    return (field_class, args, kwargs)

Solved the problem by removing the rules and adding the following method to AutoOneToOneField:

def south_field_triple(self):
    "Returns a suitable description of this field for South."
    from south.modelsinspector import introspector
    field_class = OneToOneField.__module__ + "." + OneToOneField.__name__
    args, kwargs = introspector(self)
    return (field_class, args, kwargs)
香草可樂 2024-09-08 06:37:52

你的规则有简单的Python相关问题。在元组中,如果里面只有单个项目,则必须添加逗号。

因此将 (AutoOneToOneField) 更改为 (AutoOneToOneField,),

但说实话,我不知道我可以使用字段内的方法而不是规则。我将应用您的补丁并提交到 django-annoying 存储库。

Your rule have simple python related problem.. In tuple, you must add comma if only single item inside.

So change (AutoOneToOneField), to (AutoOneToOneField,),

But to be honest, i didn't know that I can use method inside field instead of rules. I will apply your patch and submit to django-annoying repository.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文