F.X. F.X. -4 years ago 71
Python Question

Can I lookup a related field using a Q object in the Django ORM?

In Django, can I re-use an existing Q object on multiple models, without writing the same filters twice?

I was thinking about something along the lines of the pseudo-Django code below, but did not find anything relevant in the documentation :

class Author(Model):
name = TextField()
company_name = TextField()

class Book(Model):
author = ForeignKey(Author)

# Create a Q object for the Author model
q_author = Q(company_name="Books & co.")

# Use it to retrieve Book objects
qs = Book.objects.filter(author__matches=q_author)

If that is not possible, can I extend an existing Q object to work on a related field? Pseudo-example :

# q_book == Q(author__company_name="Books & co.")
q_book = q_author.extend("author")

# Use it to retrieve Book objects
qs = Book.objects.filter(q_book)

The only thing I've found that comes close is using a subquery, which is a bit unwieldy :

qs = Book.objects.filter(author__in=Author.objects.filter(q_author))

Answer Source

From what I can tell by your comment, it just looks like you're trying to pass a set of common arguments to multiple filters, to do that you can just unpack a dictionary

The values in the dictionary can still be q objects if required as if it were a value you would pass in to the filter argument normally

args = { 'author__company_name': "Books & co" }
qs = Book.objects.filter(**args)

args['author_name'] = 'Foo'
qs = Book.objects.filter(**args)

To share this between different models, you'd have to do some dictionary mangling

author_args = { k.lstrip('author__'): v for k, v in args.items }
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download