Django Querysets, a Quick Intro

AP Jama
APJama
Published in
4 min readJun 25, 2019

Django Querysets are one of the most powerful tools available to you as a developer. And there’s a lot of it really interesting stuff that can be done with them. Here’s a quick run down of some basic stuff, and not so basic stuff.

generic placeholder photo to scare you

What are they?

Django ships with its own ORM (object relational manager). Think of it as like a layer between your Django application and your database. It takes stuff from your database, and it translates it into objects django can understand.

According to the django documentation:

Internally, a QuerySet can be constructed, filtered, sliced, and generally passed around without actually hitting the database. No database activity actually occurs until you do something to evaluate the queryset.

At the very centre of the django ORM is models. So these querysets can called on the model managers, which if you’re inheriting from models.Model, you’re going to have access to! Their format is also the same:

SomeModel.objects.QUERYMETHOD

What can I do with them [basics]?

I can get a single object (by using .get)

House.objects.get(id=4)

It will return: a house object

Things to note: if this query returns more than one, django throws an error [ MultipleObjectsReturned]. And if you don’t have any objects, you’ll get the DoesNotExisterror. So only use this if you think you’ll only get ONE and ONE thing ONLY.

I can get all the objects (by using .all)

House.objects.all()

It will return: a queryset (an iterable list of all instances [houses])

I can get filter objects (by using .filter)

House.objects.filter(type="detached")

Things to note: I am going to get a list of detached houses back.

But I might want to exclude detached house. So, I’d use the exclude method like this:

House.objects.exlcude(type="detached")

I can get the first and I can get the last (by using .first/.last)

House.objects.first()

It will return: a single house instance

Things to note: the item being returned here will be the house with the smallest primary key, if no other explicit ordering has been provided. So, the house that first go saved in the database. The opposite is true for .last().

I can get latest (by using .latest)

House.objects.latest('pub_date')

It will return: a single instance

Things to note: “pub_date” here represents a field that can be ordered. So, here’s we’re saying, give me the house with the latest date. But suppose you don’t want to explicitly say the field name everytime you want to get the latest. Easy, just go in the meta class of the model definition, and add the following:

class Meta:
get_latest_by = 'pub_date'

That way, anytime I want to get the latest house by pub_data, I can just make the following query:

House.objects.latest()

I can get a list of values (by using .values)

Sometimes I don’t want to get lots of house instances. Sometimes I just want to get the house prices and nothing else.

House.objects.all().values('price')

You’ll essentially get a list of dictionaries back that look like the following:

{'price': 10000}, {'price': 1002000}, {'price': 102029}

I can get a flat list of values (by using .values_list)

House.objects.all().values_list('price')

You’ll essentially get a list of tuples back that look like the following:

[(10000,), (1002000,), (102029,)]

If you wanted to, you can get a flat list too, by adding keyword argument flat=True

House.objects.all().values_list('price', flat=True)

What can I do with them [not so basics]?

Minimise trips to related tables (by using select_related)

Suppose you’ve a table that has a foreign key pointing somewhere. If you were to use a get method to get that object, and then do something like this:

#first trip to db
house = House.objects.get(id=6)
#second trip to db
house.owner

But if I use select_related, during my first trip to db, I bring back the tables of related stuff.

# only trip needed to get both the house object and the owner object related to it
House.objects.select_related(id=6)

Minimise trips to related tables (by using prefetch_related)

This essentially works in the exact same way as select_related. The only difference is that select_related is limited to foreign key and one-to-one relationships.

Prefetch_related does a separate look up for each relationship but then joins them, so that from a trips perspective, you’re only ever doing one.

Get differences and unions of querysets (by using union and difference)

Sometimes you want to compare two or more querysets, by using these methods you can keep items that present in all, or items that are only present in one. That canonical example used for demonstrating this is the following:

qs1.difference(qs2, qs3)

.difference as a method can only be called on querysets, so it can’t be called on the model itself.

For more methods, check out the queryset api documentation. Or get at me on my twitter.

--

--