How I Created a Blog Application Using Django

5/5 - (2 votes)

In this tutorial series, we are going to take a big step on our web development journey by creating a blog application using the Django web framework. We will design the application in such a way that the user can create, edit and delete posts.

Having completed the portfolio website project, I expect you to have, among other things, a basic knowledge of Django as this project is going to be a little bit advanced. This is just to speed up your learning process. But if you are just starting to learn Django, you can still follow along with my thorough explanation.

This blog application will span more than three series as we add more advanced features such as comments, images, a rich text editor, pagination, and so much more.

πŸ’‘ Part 2: How I Created a Blog Application Using Django – Part 2

Getting Started

We won’t spend much time in this section. Just follow the instructions on your Ubuntu terminal to get your system ready for this project.

Step 1: Create a new directory called django_project

mkdir django_project && cd django_project

Step 2: Install Django in a virtual environment

python3 -m venv .venv
source .venv/bin/activate

pip install django tzdata

django-admin startproject project .
python3 manage.py startapp blog

Step 3: Perform a migration

python3 manage.py migrate

Step 4: Register the app in the project’s settings.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # custom app
    'blog',
]

The Database Model

A database is queried using a programming language other than Python. If you are not comfortable with Structured Query Language (SQL), working with databases can be a big challenge.

Django got us covered with its Object Relation Mapper (ORM) which turns model classes into a database table. So, all we need to do is to define the classes and Django will do the rest.

Go to blog/models.py file and add this:

from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse


STATUS = (
    ( 0, 'Draft'),
    (1, 'Publish')
)

class Category(models.Model):
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name


class Post(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts')
    title = models.CharField(max_length=255, unique=True)
    body = models.TextField()
    slug = models.SlugField(max_length=255, unique=True)
    created_on = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)
    categories = models.ManyToManyField('Category', related_name='posts')
    status = models.IntegerField(choices=STATUS, default=0)

    class Meta:
        ordering = ['-created_on']

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('blog_detail.html', kwargs=({'slug': self.slug}))

On the top, we import the models module that will be used to create tables and their fields; the User model to handle user accounts and authentication, and the reverse() function to generate URLs.

We then create two classes that inherit the model.Model class. Our models become a subclass of models.Model. This is done on all models created with Django.

The Category class or model is needed to store the name of the category of a post. The CharField is used because we only want short strings as indicated by the limited number of text defined. This was also the case for the title in Post model.

The SlugField enables us to add slugs to our blog. To understand what a slug is and how it works, this detailed article comes in handy. Both the slug and the title have an argument, unique=True. This tells Django not to accept any duplicated strings. The TextField is for long text. In this field, we will write our blog content.

The DateTimeField is self-explanatory but it has an argument, auto_now_add=True. What this means is that whenever an instance of the Post class is created, the current date and time is assigned to this field. The argument, auto_now=True does something similar but only when an instance of the Post class is saved. So, when you make some adjustments to the blog post, the last_modified is updated.

The author field uses a ForeignKey. This allows for a many-to-one relationship. That is, for a given user to be the author of many different blog posts. This many-to-one relationship has an on_delete option set to CASCADE.

What this means is that when a user is deleted, we don’t want the blog post related to the user hanging around. We want them deleted as well. The related_name argument makes it easy to access a list of posts by a given user using author.blog_posts.

The ManyToManyField allows for a many-to-many relationship. It is in this field that we link the two model classes in such a way that many categories can be assigned to many posts.

Notice that there is a tuple named STATUS defined to separate drafts from published posts. This was done in the status field.

The Post model has a Meta class. This tells Django to store post in descending order (as shown by the negative prefix) based on the created_on field. The __str__ method is used to represent the class object in a human-readable form.

The get_absolute_url method returns a URL it builds using the reverse function.

Having created the database, let’s create the migration files with the makemigrations command. Then we migrate the tables.

python3 manage.py makemigrations blog
python3 manage.py migrate

Creating an Admin Panel

Django has an inbuilt admin interface to create and manage the Post model. To use the admin panel, we have to create a superuser account. Run the following command and follow the instructions therein. Remember that the password is not visible on the terminal.

python3 manage.py createsuperuser

Start the local with the following command and go to http://127.0.0.1/admin in your browser.

python3 manage.py runserver

Once you log in, you will see the admin panel. But our Post model is nowhere to be found. That’s because we have not registered our model. So, let’s do so in the admin.py file located in the blog folder.

from django.contrib import admin
from .models import Post, Category


class PostAdmin(admin.ModelAdmin):
    list_display = ('title', 'slug', 'status', 'created_on',)
    list_filter = ('status',)
    search_fields = ['title', 'body']
    prepopulated_fields = {'slug': ('title',)}


admin.site.register(Post, PostAdmin)
admin.site.register(Category)

We customize the way data is displayed to make the admin more efficient.

The prepopulated_fields automatically generate the value for the slug field using the title field. Without setting this, adding a slug becomes tedious. With this in place, once we type the name of the blog article, the slug field is automatically populated.

The search_fields sets which attributes to search for in the database. The list_filter filters the post based on the status field.

Now everything is set, open the admin once again and add blog articles to it.

We can see everything we customized is displayed. The code for this first series is on my GitHub page.

πŸ§‘β€πŸ’» Recommended: How I Built a QR Code Generator in Django Web Application

Conclusion

So far in this project on creating a blog application, we have set up Django in our system, created our models and customized the admin interface. No doubt, the models will take you a lot of time to digest especially if you are a beginner. Well, you have all the time you need.

In the second part series, we will continue from where we stopped by creating the views, mapping the URLs to the views, and setting the templates to display the blog articles. πŸ‘‡πŸ‘‡πŸ‘‡

πŸ’‘ Part 2: How I Created a Blog Application Using Django – Part 2