Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to "filter" by "exists" in Django?

I would like to filter a queryset by whether a certain subquery returns any results. In SQL this might look like this:

SELECT * FROM events e WHERE EXISTS
    (SELECT * FROM tags t WHERE t.event_id = e.id AND t.text IN ("abc", "def"))

In other words, retrieve all events which are tagged with one of the specified tags.

How might I express this using Django's QuerySet API on models Event and Tag?

like image 966
Roman Starkov Avatar asked Oct 15 '10 17:10

Roman Starkov


People also ask

What is the manytomany field in Django filters?

The ManyToMany relationship field provides intuitive access to semi-complex data relationships. Knowing how to leverage it within Django filters can make your queries more efficient. To illustrate the ManyToMany field in action, let’s create some simple database models representing publicly-traded securities and their historic market prices.

What is the use of a Q OBJECT in Django?

Django provides the Q object to simplify more complex lookups. I would recommend anyone that finds themselves without a clue as to the proper query syntax to check that class out.

What are the downsides of using an extra query in Django?

The main downside is that if you refer to some table alias of the queryset in the raw SQL, then it is possible that Django might change that alias (for example, when the queryset is used as a subquery in yet another query). You should be very careful whenever you use extra ().

How does Django’s foreignkey work?

By default, Django’s ForeignKey emulates the SQL constraint ON DELETE CASCADE — in other words, any objects with foreign keys pointing at the objects to be deleted will be deleted along with them. For example:


2 Answers

You can do something like this:

q = Event.objects.filter(tag__text__in = ['abc', 'def'])

Assuming that there is a ForeignKey from Tag to Event.

Explanation: You are filtering Event objects based on a specific criteria. Using the double underscore syntax you are accessing the text attribute of the Tag instances and then attaching the IN condition. You don't have to worry about the join on foreign key; Django does that for you behind the scenes. In case you are curious to see the query generated, you can print it:

print q.query
like image 130
Manoj Govindan Avatar answered Oct 05 '22 04:10

Manoj Govindan


Manoj's solution may cause a problem when there are multiple tags for an event.

The SQL inner join returns all the rows so events may have duplicate results, the solution is to add the distinct method.

q = Event.objects.filter(tag__text__in = ['abc', 'def']).distinct()

like image 39
Matous Hora Avatar answered Oct 05 '22 05:10

Matous Hora