Contact Information

KodeBlog

We're Available 24/ 7. Drop us an email.

Django Models

Our application does not use a database, yet. In this tutorial, we will connect our Django project to the MySQL database, then we will create some models and then, we will create database tables based on our models, using Django migrations. We will continue building on where we ended in the previous section.

Django comes with a built-in Object Relational Mapper that is database agnostic. The ORM allows us to interact with the dabase using classes and the SQL statetements are automatically generated for us in the background.

Topics to be covered

We will cover the following topics in this lesson

  • Django Database Setup & Configuration
  • How to create models in Django
  • How to generate database migrations
  • How to run database migrations
  • Django Shell
  • Django Database Seeding
  • Summary

Django Database Setup & Configuration

Django supports many database engines such as MySQL, SQL Server, Postgres, SQLite etc. By default, SQLite is supported our of the box but other engines require you to install third-party libraries. We will work with MySQL database so we need to install some third-party packages

MySQL Django Packages

We need to install the prerequiste libraries for MySQL first then install the database package if we haven't yet done so.

Run the following command if you are using Ubuntu

sudo apt-get install python-dev default-libmysqlclient-dev

On MacOS, you will need to run the following command

brew install mysql-client

If you are on Windows, you can use Ubuntu within windows which is supported from version 10 or you can install binary files

Finally, we can install our mysqlclient library like so

pip install mysqlclient

Django MySQL Database Settings

The database settings are stored in settings.py file under the project folder.

Open the file settings.py and locate the following section

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

We will use MySQL as the database engine so update the above code as follows

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'bookstore',
        'USER':'root',
        'PASSWORD': 'db_password',
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }   
}

HERE,

  • 'ENGINE': 'django.db.backends.mysql', sets the database engine to MySQL
  • 'NAME': 'db_name', sets the database name that you should exist in MySQL
  • 'USER':'db_user' defines the user name that will be used to connect to MySQL
  • 'PASSWORD': 'db_password' sets the password to be used when connecting to MySQL
  • 'HOST': '127.0.0.1', sets the IP address to the server that we want to connect to.
  • 'PORT': '3306', specifies the port number where MySQL is running.

Let's now create the database bookstore in MySQL by running the following SQL command against MySQL

CREATE SCHEMA bookstore;

Finally, we test the database connectivity by running the following command

python manage.py migrate

You should be able to get the following results

Django database migrate

As you can see from the above results, Django comes with initial database migrations for the admin panel and authentication. If you get the above results then you managed to connect successfully to the database.

How to create models in Django

"A model is the single, definitive source of information about your data. It contains the essential fields and behaviors of the data you're storing. Generally, each model maps to a single database table"

We will start by creating a new model for category.

Open the file models.py located in /bookstore/categories and update the code as follows

from django.db import models

# Create your models here.
class Category(models.Model):
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name

HERE,

  • from django.db import models imports the models module from the package django.db
  • class Category(models.Model): defines class Category that accepts models.Model as a parameter
  • name = models.CharField(max_length=20) defines a field called name that is of CharField type with a maximum length of 20
  • def __str__(self): defines a method __str__ that is called when you call the toString method on the class.

Next we will create the model for Authors.

Open the file models.py that is located in the directory /bookstore/authors and update the code as follows

from django.db import models

# Create your models here.
class Author(models.Model):
    name = models.CharField(max_length=50)

    def __str__(self):
        return self.name

HERE,

  • The above code is the same as the code for the categories model except the maximum length is 50.

Finally, we will create the model for books. Open the file models.py that is located in /bookstore/books and update the code as follows

from django.db import models
from authors.models import Author
from categories.models import Category

# Create your models here.
class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    description = models.TextField()
    category = models.ManyToManyField(Category)

    def __str__(self):
        return self.title

HERE,

  • from authors.models import Author imports the model Author from the package authors.
  • from categories.models import Category imports the model Category from the package categories.
  • class Book(models.Model): defines a class Book that extends the model class
  • title = models.CharField(max_length=100) defines a title field that is of CharField type with a maximum length of 100.
  • author = models.ForeignKey(Author, on_delete=models.CASCADE) author is a foreign-key to the Author model. There is a 1-Many relationship between book and author. In the database, it will be the author_id column.
  • description = models.TextField() the description will be TextField. The text length has no limit in the database.
  • category = models.ManyToManyField(Category) category is a ManyToManyField. There is a Many-To-Many relationship between category and book. Each book can have n categories, and each category has n books. In the database, we will have a table with values: book_id and category_id
  • def __str__(self): defines the toString method which returns the title of the book

In the next section, we will create database migration files

How to generate database migrations

A migration is a process of updating database schema based on our models. By default, some Django apps like auth have some models that need to be migrated.

But, the tables related to our models, have not been created. That’s because we need to create a migration for them so Django can create or update the schema based on that. Imagine you need to change your models. Using the migration files, Django detects which tables should be changed which will remain unchanged. Creating and updating migrations is automatic:

Run the following command in the terminal to generate the database migration files.

python manage.py makemigrations

After running the above command, you should be able to get the following results

Django makemigrations

As you can see from the above image, Django has created migration files based on the models we created in the migrations directory in each application.

We can view the SQL statement that will be generated by Django to run against the database using the following command

python manage.py sqlmigrate app_name migration_file

For example, if you want to view the migration file to be generated for the Category model, you can run the following command

python manage.py sqlmigrate categories 0001_initial

Executing the above code produces the following results

--
-- Create model Category
--
CREATE TABLE `categories_category` (
    `id` INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `name` VARCHAR(20) NOT NULL
);

Notice in the SQL statement, the id column which is the primary key has automatically been added for us.

python manage.py sqlmigrate authors 0001_initial

Produces the following statement

--
-- Create model Author
--
CREATE TABLE `authors_author` (
    `id` INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `name` VARCHAR(50) NOT NULL
);

Let's now see the statement that will be generated for the books model

python manage.py sqlmigrate books 0001_initial

The above command produces the following results

--
-- Create model Book
--
CREATE TABLE `books_book` (
    `id` INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `title` VARCHAR(100) NOT NULL,
    `description` LONGTEXT NOT NULL,
    `author_id` INTEGER NOT NULL
);

CREATE TABLE `books_book_category` (
    `id` INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `book_id` INTEGER NOT NULL,
    `category_id` INTEGER NOT NULL
);

ALTER TABLE `books_book` ADD CONSTRAINT `books_book_author_id_8b91747b_fk_authors_author_id` FOREIGN KEY (`author_id`) REFERENCES `authors_author` (`id`);

ALTER TABLE `books_book_category` ADD CONSTRAINT `books_book_category_book_id_category_id_366b4d90_uniq` UNIQUE (`book_id`, `category_id`);

ALTER TABLE `books_book_category` ADD CONSTRAINT `books_book_category_book_id_93f0cbfc_fk_books_book_id` FOREIGN KEY (`book_id`) REFERENCES `books_book` (`id`);

ALTER TABLE `books_book_category` ADD CONSTRAINT `books_book_category_category_id_f94af53f_fk_categorie` FOREIGN KEY (`category_id`) REFERENCES `categories_category` (`id`);

As you can see from the above results, Django has created two tables and a couple of relationships automatically. This is the power of migrations. They allow us to create classes that are related and generate the complex SQL statements in the background.

Its not necessary to run the above command but I just wanted to show you what is going on in the background when you run migrations.

How to run database migrations

Now, we can apply the changes to our database schema

Run the following commad

python manage.py migrate

You should be able to see the following results in the terminal

Django Migrate

As you can see in the above image, the migrations authors.0001_initial, categories.0001_initial, and books.0001_initial have successfully been applied. If you check in the database, you should be able to see the following tables as shown in the image below

MySQL Bookstore DB

The tables for both default and app migrations have successfully been created for us. We don't have to manually maintain the database.

Django Shell

Django is an interactive terminal program that loads the Django framework of our application and allows us to perform activies such as inserting, updating, deleting and retrieving data from the database.

You can start the shell interactive program by running the following command

python manage.py shell

You should be able to get an interactive program in the terminal

Run the following commands

from authors.models import Author
a = Author(name='Rodrick Kazembe')
a.save()

HERE,

  • from authors.models import Author imports the Author model
  • a = Author(name='Rodrick Kazembe') creates an instance of our model with Rodrick Kazembe as the value of the attribute name
  • a.save() calls the save method of the instance variable a which saves the record in the database

If you run the following command in MySQL

SELECT * FROM bookstore.authors_author;

Then you should be able to see the following results

MySQL Select

As you can see from the above results, you an create, read, update and delete data from the shell program. The shell program is useful for quickly interacting with model methods before you write the code that will be interacting with the database.

Django Database Seeding

Database seeding is the process of generating fake database records for testing purposes. You may be working on an application that needs to paginate results from the database and seeding is a great way of generating lots of dummy records at once without creating them one by one.

In this section, we will install a package that we will use to generate dummy records.

Run the following pip command

pip install django-seed

After the above command has successfully installed, you can create dummy records using the following command

python manage.py seed categories --number=10

HERE,

  • The above command creates 10 dummy records in the database.

We can now run the following SQL SELECT query

SELECT * FROM categories;

You should be able to see the following results

Django database seeding

The seed command generated 10 records as we specified in the command. Database seeding is something that should be useful during development.

Summary

Django uses models to interact with the database. Django comes with a built-in Object Relation Mapper (ORM) that allows you to interact with the database using classes and in the background, it generates the necessary SQL statements. Migrations are used to automate the process of creating and maintaing database tables. Django has an interactive terminal program shell that loads the framework and allows you to interact with models. You can use third-party packages to automatically seed database records.

Author: Rodrick Kazembe

Rodrick is a developer who works on Desktop, Web and Mobile Applications. He is familiar with Python, Java, JavaScript, C++, C#, Kotlin, PHP, Python and the list goes on. Rodrick enjoys sharing knowledge especially when it comes to technology.

Django Online Bookstore, Course Project

Django Database Queries

Leave A Reply