Lukasz Koziara
Lukasz Koziara

Reputation: 4320

Defining django queryset with Q objects with foreign key

Example model:

class Book(models.Model):
    title = models.TextField()

class Author(models.Model):
    book = models.ForeignKey(Book)
    name = models.CharField(max_length=50)

and some example data:

Book:
id  title
1   test111
2   test222
3   test333
4   test444

Author:
book_id  name
1        test111
1        test222
2        test222
2        test333
3        test111
3        test333
4        test111
4        test333

I want get all books which authors name contains '111' and '333' (so all books which have at least 2 authors: first with 111 in name, second with 333 in name)

I can reach this goal by using chain query:

books = Book.objects.filter(author__name__icontains="111").filter(author__name__icontains="333")

which return two books with id: 3 and 4

Is there any way to reach above goal by using Q objects?

Upvotes: 3

Views: 5432

Answers (2)

Velodee
Velodee

Reputation: 41

This one is for dynamic auth list:

pk_list = qs.values_list('pk', flat=True)  # i.e [] or [1, 2, 3]

if len(pk_list) == 0:
    Book.objects.none()

else:
    q = None
    for pk in pk_list:
        if q is None:
            q = Q(pk=pk)
        else:
            q = q | Q(pk=pk)

    Book.objects.filter(q)

Upvotes: 0

dani herrera
dani herrera

Reputation: 51745

You can combine reduce and Q, see The power of django’s Q objects post.

from django.db.models import Q
import operator
auths = [ "111", "333" ]
query = reduce(operator.and_, [ Q(author__name__icontains=x) for x in auths ] )
books = Book.objects.filter( query )

Upvotes: 6

Related Questions