Create a blog application with django, part 2: create django models

Throughout this tutorial, you will encounter the terms project and application over and over. In Django, a project is considered a Django installation with some settings. An application is a group of models, views, templates, and URLs. Applications interact with the framework to provide some specific functionalities and may be reused in various projects. You can think of the project as your website, which contains several applications such as a blog, wiki, or forum, that can be used by other projects also.

Creating Django application

Now, let's create our first Django application. We will create a blog application from scratch. From the project's root directory, run the following command:

(venv) mypc:~/venv/mysite$ python manage.py startapp blog

This will create the basic structure of the application, which looks like this:

blog/

  __init__.py
  admin.py
  apps.py
  migrations/
      __init__.py
  models.py
  tests.py
  views.py

These files are as follows:

  • admin.py: This is where you register models to include them in the Django administration site, using the Django admin site is optional.
  • apps.py: This includes the main configuration of the blog application.
  • migrations: This directory will contain database migrations of your application. Migrations allow Django to track your model changes and synchronize the database accordingly.
  • models.py: Data models of your application, all Django applications need to have a models.py file, but this file can be left empty.
  • tests.py: This is where you can add tests for your application.
  • views.py: The logic of your application goes here; each view receives an HTTP request, processes it, and returns a response.

Creating Django models

We will start designing our blog data schema by defining the data models for our blog. A model is a Python class that subclasses django.db.models.Model, in which each attribute represents a database field. Django will create a table for each model defined in the models.py file. When you create a model, Django provides you with a practical API (Application Programming Interface) to query objects in the database easily.

First, we will define a Post model. Add the following lines to the blog/models.py file of your blog application:

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User

class Post(models.Model):
   STATUS_CHOICES = (
       ('draft', 'Draft'),
       ('published', 'Published'),
   )
   title = models.CharField(max_length=250)
   slug = models.SlugField(max_length=250,
                           unique_for_date='publish')
   author = models.ForeignKey(User,
                              on_delete=models.CASCADE,
                              related_name='blog_posts')
   body = models.TextField()
   publish = models.DateTimeField(default=timezone.now)
   created = models.DateTimeField(auto_now_add=True)
   updated = models.DateTimeField(auto_now=True)
   status = models.CharField(max_length=10,
                             choices=STATUS_CHOICES,
                             default='draft')

   class Meta:
       ordering = ('-publish',)

   def __str__(self):
       return self.title

This is our data model for blog posts. Let's take a look at the fields we just defined for this model:

  • title: This is the field for the post title. This field is CharField, which translates into a VARCHAR column in the SQL database.
  • slug: This is a field intended to be used in URLs. A slug is a short label that contains only letters, numbers, underscores, or hyphens. We will use the slug field to build beautiful, SEO-friendly URLs for our blog posts. We have added the unique_for_date parameter to this field so that we can build URLs for posts using their publish date and slug. Django will prevent multiple posts from having the same slug for a given date.
  • author: This field is a foreign key. It defines a many-to-one relationship. We are telling Django that each post is written by a user, and a user can write any number of posts. For this field, Django will create a foreign key in the database using the primary key of the related model. In this case, we are relying on the User model of the Django authentication system. Read more about Django foreign key here .
  • body: This is the body of the post. This field is a text field, which translates into a TEXT column in the SQL database.
  • publish: This datetime indicates when the post was published. We use Django's timezone now method as the default value. This returns the current datetime in a timezone-aware format. You can think of it as a timezone-aware version of the standard Python datetime.now method.
  • created: This datetime indicates when the post was created. Since we are using auto_now_add here, the date will be saved automatically when creating an object.
  • updated: This datetime indicates the last time the post was updated. Since we are using auto_now here, the date will be updated automatically when saving an object.
  • status: This field shows the status of a post. We use a choices parameter, so the value of this field can only be set to one of the given choices.

Django comes with different types of fields that you can use to define your models, read more .

The Meta class inside the model contains metadata. We tell Django to sort results in the publish field in descending order by default when we query the database. We specify descending order using the negative prefix. By doing so, posts published recently will appear first.

The __str__() method is the default human-readable representation of the object. Django will use it in many places, such as the administration site.

Activating your application

In order for Django to keep track of our application and be able to create database tables for its models, we have to activate it. To do this, edit the mysite/settings.py file and add blog.apps.BlogConfig to the INSTALLED_APPS setting. It'll look like this:

INSTALLED_APPS = [
   'django.contrib.admin',
   'django.contrib.auth',
   'django.contrib.contenttypes',
   'django.contrib.sessions',
   'django.contrib.messages',
   'django.contrib.staticfiles',

   'polls.apps.BlogConfig', # New
]

The BlogConfig class is your application configuration. Now Django knows that our application is active for this project and will be able to load its models.

Creating and applying migrations

Now that we have a data model for our blog posts, we will need a database table for it. Django comes with a migration system that tracks the changes done to models and allows to propagate them into the database. The migrate command applies migrations for all applications listed in INSTALLED_APPS; it synchronizes the database with the current models and existing migrations.

In the root directory of your project, run the following command:

$ python manage.py makemigrations blog

You should see something like the following:

Migrations for 'blog':
 blog/migrations/0001_initial.py
   - Create model Post

Django just created the 0001_initial.py file inside the migrations directory of the blog application. You can open that file to see how a migration appears. Migrations are how Django stores changes to your models (and thus your database schema).

Let's take a look at the SQL code that Django will execute in the database to create the table for our model. The sqlmigrate command takes migration names and returns their SQL without executing it. Run the following command to inspect the SQL output of our first migration:

$ python manage.py sqlmigrate blog 0001

BEGIN;
--
-- Create model Post
--
CREATE TABLE "blog_post" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(250) NOT NULL, "slug"  varchar(250) NOT NULL, "body" text NOT NULL, "publish" datetime NOT NULL, "created" datetime NOT NULL, "updated" datetime NOT NULL, "status" varchar(10) NOT NULL, "author_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "blog_post_slug_b95473f2" ON "blog_post" ("slug");
CREATE INDEX "blog_post_author_id_dd7a8485" ON "blog_post" ("author_id");
COMMIT;

The exact output will vary depending on the database you are using. The example above is generated for SQLite, as you can see Django generates the table names by combining the app name and the lowercase name of the model blog_post, but you can also specify a custom database name for your model in the Meta class of the model using the db_table attribute. Django creates a primary key automatically for each model, but you can also override this by specifying primary_key=True in one of your model fields. The default primary key is an id column, which consists of an integer that is incremented automatically. This column corresponds to the id field that is automatically added to your models.

Let's sync our database with the new model. Run the following command to apply existing migrations:

$ python manage.py migrate
Operations to perform:
 Apply all migrations: admin, auth, contenttypes, blog, sessions
Running migrations:
 Applying blog.0001_initial... OK   # Our blog app
 Applying sessions.0001_initial... OK

We just applied migrations for the applications listed in INSTALLED_APPS, including our blog application.

If you edit your models.py file in order to add, remove, or change fields of existing models, or if you add new models, remember to run the following commands:

  • Run python manage.py makemigrations to create migrations for those changes
  • Run python manage.py migrate to apply those changes to the database.

That's it for now. The next tutorial is to create an administration site for our blog application so that we can register our models.


If you like my content, please consider buying me a coffee.
Thank you for your support!

Related posts