在Django 1.3中合并重复项的最佳方法?

时间:2012-01-14 02:56:24

标签: python django django-models django-1.3

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

您知道如何修复此方法或其他合并对象的方法吗?

编辑:更多详情

我有3个型号:A,B,C

A有一个指向C到B的多个字段“m2mfield”。

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

'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.

我认为我得到的代码片段与使用和不使用中间模型的ManyToMany关系没有任何区别。这就是为什么我正在寻找某种方法来修复代码或其他方式来实现我想要的东西(合并)。

2 个答案:

答案 0 :(得分: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()

答案 1 :(得分:0)

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

在代码段中,您粘贴了一个应该通过模型识别的代码,以使合并正常工作,它启动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不是,当前代码也不能处理。