Django applications use a SQLite by default. In VScode, the database is stored in a file called db.sqlite3
.
The great thing about this is you can set up a Django project without having to set up a database yourself. Of course, you can use PostgreSQL or mySQL, which is more suitable for large applications. But for personal projects, SQLite is often sufficient.
The problem with db.sqlite3
is you can’t open the file and see what’s inside.
When I was a Django beginner, I never looked at the database and always relied on Django Admin or the shell. Django Admin won’t display all of the tables in your database and the shell is only useful if you know where to look.
Thankfully, there are VScode extensions that will allow you to explore the actual database for your Django project.
This is an important tool for beginners. By understanding the different tables in the Django database, you can begin to understand how Django applications work.
For example, did you know that Django applications have 10 tables in the database? That is before you create any models.
In this tutorial, we are going to install SQLite Viewer in VScode. It is a free VScode extension that will allow us to explore our database inside VScode.
Once installed, I will show you some database features of a simple blogging application that might not be obvious from Django admin.
Install SQLite Viewer
In VScode, go to the extensions tab. It is the 5th icon from the top (see image).
Search for SQLite Viewer
. If there are multiple, then select one by Florian Kampfer.
Alternatively, go to this link to install the extension.
https://marketplace.visualstudio.com/items?itemName=qwtel.sqlite-viewer

Now that the viewer has been installed, let’s explore.
1. Django has tables of its own

In the image above, there is a list of 16 tables but I only added 3 models (Post, Category and Tags) as part of my project.
In settings.py
, there is a list of installed apps. Each time you start a new app or install certain extensions, you have to add the name to the list of installed apps:
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"blog",
"django_summernote",
]
The first 6 apps: admin
, auth
, contenttypes
, sessions
, messages
and staticfiles
were installed with Django. These apps will have models, so when you run initial migrations, tables in the database will be created.
This is why you can’t run python manage.py createsuperuser
before python manage.py migrate
has been run. The migration creates the auth_user
table hasn’t been created yet.
2. You can see which migrations have been applied
The first table django_migrations
keeps a record of which migrations have been applied to the database in the order they were applied.
This is helpful when you have migration errors. Sometimes, when you’re working on multiple branches, the migration files in your apps and the result of python manage.py showmigrations
might not match what’s in your database.
Therefore it is useful to know what migrations are in the database. Multiple branches may have different migration records, but they all use the same database.
If you want to better understand how migrations work, check out my guide.
3. Foreign Key columns store IDs, not objects
In Django admin, fields that use a Foreign Key have a handy link to the related object.
In the database, the primary key is stored instead.

4. The database stores the image path, not the image
This is a common misconception. Even though Django models have an Image Field, relational databases are not capable of storing images.
As we can see in the screenshot below, the feature_image
field stores the location of the image.

5. ManyToMany relations get their own table
In this application, blog posts can be assigned one or more tags. There are separate models for Post
and Tag
with a ManyToManyField
linking the two (Github: models.py).
However, there is no reference to tags in the blog_post
table. There are no references to posts in the blog_tag
table either.
So how are Many-to-Many relationships stored in the database?
The relationship is stored in its own table.

For every tag assigned to a blog post, there will be a row in the database. We can see post 13 has been given two tags because it has two rows. Post 3 and 14 have one tag each.
6. Some plugins will add tables to your database
In a previous tutorial, I installed Summernote to add a text editor for my blog posts.
After installing Summernote, I had to add it to my list of INSTALLED_APPS
and run migrations.
As I have SQLite viewer installed, I could go into the database and see what changes Summernote made. By looking at the database, I could see that Summernote keeps a record of all the images a user included in the post content. It stores the file name, the path to the file and the date/time it was uploaded.

Conclusion
SQLite Viewer is a free VScode extension that will let you explore SQLite databases, which comes installed with Django.
Having visibility of the database is essential for beginners to understand how Django works. Django has to create several tables in the database just to provide core features like users and session management.
It allows you to view data that is hidden from the admin panel.
When you install 3rd party plugins that require migrations, viewing the tables it creates will help you understand how it works.
You can also see how relations between objects are stored in the database. For Foreign Keys, the ID of the linked object is stored in the database. Many to many fields are stored in their own table.
Finally, you can use the database to view a list of migrations that have been applied to the database. This is useful when working on multiple branches, where each branch will have different migration files.