繁体   English   中英

如何在Django中更新manytomany字段?

[英]How to update manytomany field in Django?

这是一个例子:

如果我有这些课程

class Author(models.Model):
    name = models.CharField(max_length=45)

class Book(models.Model):
    name = models.CharField(max_length=45)
    authors = models.ManyToManyField(Author)

在数据库中,我有一个名为“George”的作者和另一个名为“Georfe”的作者。 最后一个是错误的。 所以我想要的是每本书都有“Georfe”作为他的作者之一取代作者“乔治”。

在SQL中真的很容易做到。 如果“George”的id = 3且“Georfe”的id = 7且关系表名称为“author_book”:

UPDATE author_book SET id=3 WHERE id=7;

用Django ORM可以做到这一点吗?

我找到了一种方法:我通过错误的作者的所有相关书籍循环,并做:

book.authors.add(Author.objects.get(id=3))
book.authors.remove(Author.objects.get(id=7))

但我发现这种解决方案并不优雅高效。 有没有循环的解决方案?

注意:此代码将删除错误的“georfe”作者,以及更新书籍以指向正确的作者。 如果你不想这样做,那么使用.remove()作为@jcdyer的回答提及。

你能做这样的事吗?

george_author = Author.objects.get(name="George")
for book in Book.objects.filter(authors__name="Georfe"):
    book.authors.add(george_author.id)
    book.authors.filter(name="Georfe").delete()

我怀疑如果你有一个明确的表连接两个模型(使用“through”关键字arg)会更容易 - 在这种情况下,你可以直接访问关系表,并且可以只做一个.update(id=george_author.id)就可以了。

使用自动生成的直通表,您可以执行两步插入和删除操作,这对于提高可读性非常有用。

george = Author.objects.get(name='George')
georfe = Author.objects.get(name='Georfe')

book.authors.add(george)
book.authors.remove(georfe)
assert george in book.authors

如果你有一个明确定义的直通表(authors = models.ManyToManyField(作者,通过= BookAuthors),那么你可以在BookAuthor上明确地改变关系。一个鲜为人知的事实是这个模型已经存在,它是由django自动生成的。通常如果您希望存储额外的数据(例如特定作者在多作者书中写过的章节),您应该只创建一个显式的直通模型。

# This line is only needed without a custom through model.
BookAuthor = Book.authors.through
book_author = BookAuthor.objects.get(author=georfe, book=great_american_novel)
book_author.author = george
book_author.save()
assert george in book.authors

对于django> = 1.11文档:

>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.add(e) # Associates Entry e with Blog b.
>>> new_list = [obj1, obj2, obj3]
>>> e.related_set.set(new_list)

此方法接受clear参数来控制如何执行操作。 如果为False (默认值),则使用remove()新集中缺少的元素,并仅添加新的元素。 如果clear=True ,则调用clear()方法,并立即添加整个集合。

和参考: 如何在django中更新m2m字段

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM