Django ORM queries and common misunderstanding/mistakes by beginners

Django ORM queries and common misunderstanding/mistakes by beginners

Django’s ORM system is a great way to work with databases. I’ve been working on different projects for the past five years, including those involving new developers. From this experience, I’ve noticed some common misunderstandings that crop up when people start using Django.

  1. The admin panel is not where data is stored

One of these misunderstandings is about the Django admin panel. This panel helps manage data in your app, but it’s not where the actual data is kept.

A lot of folks, especially those new to Django, think that the admin panel is the main place where data is stored. But in reality, Django supports different databases like MySQL and PostgreSQL, and it starts with SQLite3 as the default. The `settings.py` file in your Django project holds the details about which database you’re using.

To see and work with the actual data, it’s better to use special apps. Programs like DBeaver, Pgadmin, or MySQL Workbench help you connect directly to your database. They show you the raw data and let you run special commands (SQL queries) to get what you need. This is useful when you want to do more complex searches or understand how the data is set up.

The point here is to make clear that the Django admin panel isn’t the same as the actual database. By using these apps, you can learn more about the real database. For beginners getting into Django, knowing this difference helps them feel more confident and skilled in using the system.

2. Not knowing about SQL statements

When people begin learning Django, they usually work with a type of database called a relational database. This is true for about 99% of cases. What’s interesting is that I’ve noticed many developers know how to create models and use ORM queries, but they might not know what’s happening behind the scenes with the actual database.

You see, Django ORM is like a translator. When you write an ORM query, Django turns it into a different kind of query that the database can understand. This special query is called an SQL query. The database knows how to deal with these SQL queries.

So, when you ask the database for data using Django ORM, it’s like telling Django to talk to the database in a language it understands. The database then finds the data and gives it to Django. But here’s the cool part: Django takes that data and turns it into objects that you can work within your code.

So, even though you might not see the SQL queries, they’re there, doing the work in the background. Django translates your ORM requests into SQL, gets the data, and then changes it into objects you can play within your program. It’s like a magical bridge between your code and the database!

If you wish to check database queries, you can use django-debug-toolbar.

3. Not understanding how lazy QuerySet works

QuerySets are lazy. The act of creating a QuerySet doesn’t involve any database activity. You can stack filters together all day long, and Django won’t actually run the query until the QuerySet is evaluated” — Django Documentation

What it really means by this is database query will not get executed until data is needed. For example

query = User.objects.filter(name__istartwith="r")
query = query.filter(is_active=False)
query = query.filter(age__lte=25)
print(query)

In the above example, the Database query will run only on the last line because that is where we want our data to be displayed or used.

query = User.objects.filter(name__istartwith="r")
print(query)
query = query.filter(is_active=False)
print(query)
query = query.filter(age__lte=25)
print(query)

In the above example, a total of 3 SQL queries will be executed because we are displaying data on lines 2, 4 & 6 respectively.

4. Not observing the number of SQL queries

Remember how we talked about Django turning our special requests into messages the database can understand? Well, these messages are called SQL statements. They’re like instructions that tell the database what we want.

But here’s the thing: every time we ask the database to do something, it takes a bit of time. It’s like asking someone for help — it takes a moment for them to respond. So, if we ask the database to do lots and lots of things, our app can start to slow down because it’s waiting for the database to finish.

Imagine you’re making a list of things you need from the store. The more things on the list, the more time it takes to find everything. It’s the same with the database — the more requests we make, the slower our app can become.

Now, there’s something called “Querysets” in Django. These are kind of like mini-requests that we can use to get specific things from the database. But here’s where it gets tricky: Querysets can sometimes be a bit lazy. In the case of relational data (ForeignKey/ManyToMany), they do not know how to get the data until explicitly mentioned by select_related or prefetch_related methods.

Think of it like this: If you’re going to the store without knowing exactly what you want, you might end up going there a bunch of times for just one thing each time. That’s like Querysets not being sure what you need and making more trips to the database.

I’m going to dive deeper into this in another article, where I’ll explain exactly how we can make sure our app only asks for what it really needs from the database. So, stay tuned for that! 😄

I hope you enjoyed this article. Hit that follow button for more such articles also follow me on Twitter for more shitposting and updates ;)