Django:在保存时更新ManyToManyField

时间:2014-01-03 13:18:17

标签: python django

我有一个Book模型,它有一个多对多字段的作者。如果我合并两本书,我想确保合并的书只有唯一的作者,没有双打。我认为实现这一目标的最佳方法是覆盖save()方法,到目前为止我已经来到了这个模型:

class Book(models.Model):
    authors = models.ManyToManyField()

    def save(self):
        authors_new = []
        authors = self.authors.all()
        for author in authors:
            if author not in authors_new:
                authors_new.append(author)
        self.authors = authors_new           #This won't work
        super(Book, self).save()

倒数第二行显然不起作用,但我似乎无法使语法正确。不过,我认为我想要实现的目标非常明显。任何人都知道正确的语法是什么?

修改1:

解释合并:我必须说我不完全理解代码(由其他人编写 - 合并发生在几个函数上),所以在这里显示它不会帮助我。它的作用是:说数据库中有两本书显然是一样的。第一本书有

title= “Harry Potter and the Philosopher’s Stone”
author=“JK Rowling”
year=1999

另一本书

title=“Harry Potter (book 1)”
author=“JK Rowling” 
pages=320

合并时,您需要选择哪本书是主要书籍。如果我选择第一个是主要的,那么合并应该最终为

title=“Harry Potter and the Philosopher’s Stone”
author=“JK Rowling”
year=1999
pages=320

问题是合并结束了作者=“JK罗琳”两次我以为我可以在保存功能中取出重复项。

编辑2:

合并发生在这个函数中,我还没写过:

def merge_model_objects(primary_object, *alias_objects):
    # Use this function to merge model objects and migrate all of 
    # the related fields from the alias objects to the primary object.

    for alias_object in alias_objects:
        meta = alias_object._meta
        for related_object in meta.get_all_related_objects():
            alias_varname = related_object.get_accessor_name()
            obj_varname = related_object.field.name
            related_objects = getattr(alias_object, alias_varname)
            for obj in related_objects.all():
                if getattr(obj, 'do_not_merge', False):
                    continue
                setattr(obj, obj_varname, primary_object)
                obj.save()

        related_objects = meta.get_all_related_many_to_many_objects()
        for related_many_object in related_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)

        alias_object.delete()
    primary_object.save()
    return primary_object

这是一个非常通用的功能,可以合并两个以上的对象,但如果我合并Book 1(= primary_object)和Book 2(= alias_object),它会将其保存为book =“JK Rowling”两次

1 个答案:

答案 0 :(得分:0)

Django将多个字段表示为多个字段。所以你可能想做类似

的事情
self.authors = self.authors.union(other_model.authors)

Python sets are collections of unique, unordered objects