Как обновить поле manytomany в 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)
В базе данных у меня есть один автор с именем "Джордж" и еще один с именем "Georfe". Последняя ошибка. Итак, я хочу, чтобы в каждой книге, в которой "Геофен", как один из его авторов, заменил ее автор "Джордж".
В SQL действительно легко сделать. Если id "George" = 3 и id "Georfe" = 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))
Но я не считаю это решение действительно элегантным и эффективным. Есть ли решение без цикла?
Ответы
Ответ 1
Примечание.. Этот код удалит плохого автора "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()
Я подозреваю, что это было бы проще, если бы у вас была явная таблица, соединяющая две модели (с аргументом "через" ), в этом случае у вас был бы доступ к таблице отношений напрямую и мог бы просто сделать .update(id=george_author.id)
на нем.
Ответ 2
С помощью автоматической сгенерированной таблицы вы можете сделать двухэтапную вставку и удаление, что приятно для читаемости.
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(Author, via = 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