Как мне использовать Django ORM для запроса этого примера «многие ко многим»?

У меня есть следующие модели:

class Author(models.Model):
  author_name = models.CharField()

class Book(models.Model):
  book_name = models.CharField()

class AuthorBook(models.Model):
  author_id = models.ForeignKeyField(Author)
  book_id = models.ForeignKeyField(Book)

При этом я пытаюсь эмулировать этот запрос с помощью Django ORM (выберите все книги, написанные конкретным автором, отметив, что у авторов может быть много книг, а у книг может быть много авторов):

SELECT book_name 
FROM authorbook, book
WHERE authorbook.author_id = 1
AND authorbook.book_id = book.id

Я прочитал эту страницу часто задаваемых вопросов на веб-сайте Django, но прежде чем изменить свою модель структура и удалить AuthorBook, мне было любопытно, смогу ли я эмулировать этот запрос, используя текущую структуру.


person Huuuze    schedule 10.02.2009    source источник


Ответы (2)


Вы должны уметь:

books = Book.objects.filter(authorbook__author_id=1)

чтобы получить QuerySet объектов Book, соответствующих вашему ограничению author_id.

Что хорошо в Django, так это то, что вы можете приготовить это и поэкспериментировать с ним в оболочке. Вы также можете найти http://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships.

person Emil Sit    schedule 10.02.2009
comment
ответ webjunkie кажется лучше. Просто изучаю Джанго сам. - person Emil Sit; 10.02.2009
comment
В общем, нет причин явно упоминать поле id в ORM. Предполагая, что у вас есть экземпляр Author, вам понадобится Book.objects.filter(authorbook__author=author). Но, конечно, ManyToManyField — это то, что нужно. - person Carl Meyer; 11.02.2009
comment
Другой пример поиска по имени автора: Book.objects.filter(authors__author_name__endswith=u' Klein') при условии, что вы используете схему на основе ManyToMany webjunkie. - person akaihola; 12.02.2009

"Авторская книга" кажется не правильно смоделированной.

Вы должны использовать ManyToManyField:

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

Затем вы можете сделать:

books = Book.objects.filter(authors__id=1)
person webjunkie    schedule 10.02.2009
comment
+1 за предложение ManyToManyField (это способ Django), -1 за то, что не знал, как это делается под капотом. - person Javier; 10.02.2009
comment
Конечно, отношения m2m используют промежуточные таблицы. Тем не менее, в этом случае это неправильно смоделировано с использованием Django. Нет смысла заставлять меня давать понять, что я знаю, как это работает под капотом. - person webjunkie; 10.02.2009