I have the following models (details are omitted):
class Author(models.Model):
name = models.CharField('name', max_length=200, blank=False)
class Book(models.Model):
title = models.CharField('title', max_length=200, blank=False)
author = models.ManyToManyField(Author, blank=False, through='Book_Author')
class Book_Author(models.Model):
book = models.ForeignKey(Book)
author = models.ForeignKey(Author)
I want to get all books whose title contains given query and whose author's name contains the same query.
Now I am doing the following:
To get all books whose title contains the word I use this code:
for word in words:
books = books.filter(Q(title__icontains=word)
To get all books whose author's name contains the word I use this code:
for word in words:
authors = authors.filter(Q(name__icontains=word))
for author in authors:
for book_author in author.book_author_set.all():
book = Book.objects.get(id=book_author.book_id)
results.append(book)
Is there any way to improve the second part?
This is the easy way:
for word in words:
books = books.filter(Q(title__icontains=word) )
books = books.filter(Q(author__name__icontains=word) )
my_books = books.distinct()
* EDITED *
If you are looking for books where title contains words OR author contains words, then the query is:
q_books = None
q_authors = None
for word in words:
q_aux = Q(title__icontains=word)
q_books = (q_books & q_aux ) if bool( q_books) else q_aux
q_aux = Q(author__name__icontains=word)
q_authors = (q_authors & q_aux ) if bool( q_authors) else q_aux
my_books = Book.objects.filter( q_books | q_authors ).distinct()
Any comment for more code readability are wellcome.