2

我找到了这段代码http://djangosnippets.org/snippets/2283/但我认为它不适用于使用另一个模型(关键字通过)的 manytomanyfields - 我在尝试合并时得到一个 AttributeError 。

你知道有什么方法可以解决这个或其他合并对象的方法吗?

编辑:更多细节

我有 3 个模型:A、B、C

A 有一个多线程字段“m2mfield”,通过 B 指向 C。

当我从 django 片段运行代码时,它失败并出现异常

'ManyRelatedManager' object has no attribute 'remove'

我认为这与 Django 源代码(django.db.models.fields.related.py 第 499 行)中的评论有关,该评论说:

# If the ManyToMany relation has an intermediary model,
# the add and remove methods do not exist.

我认为我得到的代码片段在有和没有中介模型的多对多关系之间没有任何区别。这就是为什么我正在寻找某种方法来修复该代码或另一种方法来实现我想要的(合并)。

4

2 回答 2

2

我最终修改了代码以处理ManyToMany“通过”模型创建的字段的情况。以下是要修改的内容:

# Migrate all many to many references from alias object to primary object.
for related_many_object in alias_object._meta.get_all_related_many_to_many_objects():
    alias_varname = related_many_object.get_accessor_name()
    obj_varname = related_many_object.field.name

    # Treatment depends on if the many_to_many field is created through another model
    if getattr(alias_object, alias_varname).through._meta.auto_created:
        if alias_varname is not None:
            # standard case
            related_many_objects = getattr(alias_object, alias_varname).all()
        else:
            # special case, symmetrical relation, no reverse accessor
            related_many_objects = getattr(alias_object, obj_varname).all()
        for obj in related_many_objects.all():
            getattr(obj, obj_varname).remove(alias_object)
            getattr(obj, obj_varname).add(primary_object)
    else:
        related_many_objects = getattr(alias_object, alias_varname).all()

        through_model = getattr(alias_object, alias_varname).through
        through_field_name = None
        for f in through_model._meta.fields:
            if isinstance(f, ForeignKey):
                if f.rel.to == primary_class :
                # f is the field in our 'through' model which points to an instance of primary_class
                    through_field_name = f.name

        for obj in related_many_objects.all():
            kwargs = {
                through_field_name: obj,
            }
            for through_obj in through_model.objects.filter(**kwargs):
                setattr(through_obj, through_field_name, primary_object)
                through_obj.save()
于 2012-01-19T16:21:46.103 回答
0

您遇到的错误意味着您尝试填充的 manytomany 字段是使用直通模型管理的。

在您粘贴的代码片段中,应该通过模型知道合并工作,它从 L55 开始:

    # Migrate all many to many references from alias object to primary object.
    for related_many_object in alias_object._meta.get_all_related_many_to_many_objects():
        alias_varname = related_many_object.get_accessor_name()
        obj_varname = related_many_object.field.name

        if alias_varname is not None:
            # standard case
            related_many_objects = getattr(alias_object, alias_varname).all()
        else:
            # special case, symmetrical relation, no reverse accessor
            related_many_objects = getattr(alias_object, obj_varname).all()
        for obj in related_many_objects.all():
            getattr(obj, obj_varname).remove(alias_object)
            getattr(obj, obj_varname).add(primary_object)  # this can't work

您必须提供merge_model_objects一个函数字典,在其中merge_model_objects可以选择一个函数来构建直通类。这段代码很可能应该替换我上面摘录的代码段的最后一行。

但是您还应该注意 A1、A2 和 C1、C2 可能相等而 B1、B2 不相等的事实,当前代码也无法处理。

于 2012-01-19T15:04:16.893 回答