Create a Blog with Django

A step-by-step guide to create a Blog from scratch with Python and Django.

Besmire Thaqi
Geek Culture

--

Photo by Kaitlyn Baker on Unsplash

Creating a personalized blog site from scratch is simpler than it seems. Especially when using specific frameworks which provide built-in features that are ready to use. Django is an awesome framework for such cases.

Creating a Django app

In this tutorial, all the necessary steps to follow for developing and maintaining the site are covered and briefly explained in the right order.

1.0 Initial setup

Assuming that Python3 is already installed, create a directory as a starting point:

# create a dir
mkdir djangoblog
# navigate to dir
cd djangoblog

1.1 Virtual environment

Creating a virtual environment is super simple. Try the command below:

# python3 -m venv <name>
python3 -m venv venv

In this way, there is virtual environment created and named as venv. Now, let’s activate it:

# source <name>/bin/activate
source venv/bin/activate

Inside the virtual environment, there is the latest version of Python (in this case: 3.9) and latest version of pip (in this case: 21.0.1). Then, let’s install Django (by default is the latest version, in this case: 3.1.7):

# pip install <package-name>
pip install django

1.2 Project setup (1)

After creating and activating the virtual environment, the next step is to create a directory and create a Django project there:

# create a dir
mkdir mysite
# navigate to dir
cd mysite
# create a django project
django-admin startproject mysite

Now, the structure of the directory is generated as shown below:

| — mysite
| | — __init__.py
| | — asgi.py
| | — settings.py
| | — urls.py
| | — wsgi.py
| — manage.py

But, what do these files mean?

  • __init__.py → A blank Python script which indicates to the Python interpreter that this directory is actually a Python package. It allows Python packages to be imported from the directories.
  • asgi.py → Provides a standard interface between async-capable Python web servers, frameworks, and applications.
  • settings.py → A file that contains the configuration of the Django project.
  • urls.py → A file that contains URL patterns for the Django project.
  • wsgi.py → A file that contains WSGI configuration properties of the Django project. It’s basically a Python script that is used to run the development server and to help deploying to a production environment.
  • manage.py → A command line utility and allows to interact with the Django project in many ways.

First, it may be confusing that there are two directories with the same name. However, the name of the main directory can still be changed with whatever name preferred.

On the other side, the second-level directory name is hardcoded in some of Django specific files, therefore; it is not recommended to change its name.

1.3 Run the project

Django comes with a built-in web server for development. To run the project, simply navigate where the manage.py file is located and try the commands:

# default run in http://127.0.0.1:8000/
python manage.py runserver
# use another port in localhost
python manage.py runserver 2000

1.4 Project setup (2)

Now that a Django project has been created, the next step is to create a Django app. Let’s navigate where the manage.py file is located and start an app:

# python manage.py startapp <name>
python manage.py startapp blog

The app has been created and named as blog. Notice that new files are generated within the director and the current structure looks like this:

|— db.sqlite3
|— mysite
| |— __init__.py
| |— asgi.py
| |— settings.py
| |— urls.py
| |— wsgi.py
|— manage.py
|— blog
| |— __init__.py
| |— admin.py
| |— apps.py
| |— migrations
| |— models.py
| |— tests.py
| |— views.py

After creating an app, Django needs to know that there is a new app in the project. To tell Django about this, check the settings file (mysite/settings.py). Here you will find the default installed apps:

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

And, here is where we add the new app as well:

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

2.0 Database models

As seen in the project structure above, there is an SQLite database generated in the Django project.

In Python, a model is a class that inherits from django.db.models.Model. Each attribute inside a model class represents a database field. First, since now there is an app created from steps mentioned above, there are also some database migrations created by default that we need to run:

python manage.py migrate

Assuming the initial migrations were executed successfully, let’s check an example of a table called Post and its fields:

An example of a defined Django model

This model is a typical example of a blog post and what is usually needed and specified for one. In the beginning, the models and the User default model from Django is imported. There is a title, a slug, the author and the content of course. The author is a foreign key to the default Django model User. The status is to specify that the post by default is just a draft, and then it will be published.

There are two more specific fields called created_at and updated_at. These will be automatically updated with the specific date+time when an instance is added or updated in the database table. The ordering of objects created will be from last to first.

Note that the __str__() method is the human readable representation of the object. This will be used by Django in many places, such as in the admin site.

To create a new table in the database, first we need to generate a migration file and then execute this migration:

# create the migration file in migrations dir
python manage.py makemigrations
# migrate changes to the db
python manage.py migrate

2.1 Admin built-in interface

Django comes with a built-in admin interface. At this point, what’s left to do is to create a superuser and login to the admin panel:

python manage.py createsuperuserUsername (leave blank to use '<username>'): <provide username>
Email address: <provide email address>
Password: <provide password>
Password (again): <provide password again>
Superuser created successfully.

When executing the command, a username, email and password is required. Afterwards, let’s re-run the development server:

# default run in http://127.0.0.1:8000/
python manage.py runserver

To access the built-in admin interface, try http://127.0.0.1:8000/admin/.

After login, only Groups and Users from Django authentication model are visible as seen in the picture below:

In order to also see the Post model created from the example above, this should be included in the admin.py file of the blog app (blog/admin.py):

An example of adding a model in the built-in admin interface

Based on the previous piece of code, the title, slug and status will be visible in the list of posts. It can be filtered by the status defined, and searching is possible by title or content. The Post model will be available in the interface:

Note that a few blog post examples are added as shown below:

3.0 Views

A view is basically a function that receives a web request and returns a web response. The goal is to create views, create HTML template for the data returned by these views, and map them with specific URLs.

Let’s dig into more code and update file (blog/views.py):

3.1 URL Patterns

When a user makes a request to the page, the Django controller checks the URLs to return the right view. Firstly, let’s a create a file in the mysite/blog directory named urls.py, which includes the code as shown below:

from . import views
from django.urls import path
urlpatterns = [
path('', views.PostList.as_view(), name='home'),
path('<slug:slug>/', views.PostDetail.as_view(), name='post_detail'),
]

Then, the URLs from the blog needs to be imported in the URLs file of mysite directory (mysite/urls.py):

from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls')),
]

3.2 Templates

Templates for views are created by using HTML, CSS and Django template language. First, let’s create a directory for templates in the base directory.

To use the templates, they need to be configured in the settings first:

# Added template directory in settings.py
TEMPLATES_DIRS = os.path.join(BASE_DIR,'templates')
...TEMPLATES = [{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [TEMPLATES_DIRS], # Template directory added here
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},]

Then, let’s have four different (*.html) files:

  • base.html → The main template, the “skeleton” of the templates. It includes the header, navigation bar, the content & the footer.
  • index.html → Extends the base.html template, using Django template language. It contains the blog entries in the main page, using the template of post_detail.html. It also includes the sidebar.html file.
  • sidebar.html → A small sidebar added in the main page.
  • post_detail.html → The detailed view of the blog post.

Let’s check how the files mentioned from above look like:

Example of templates using HTML, CSS and Django template language, inspired by djangocentral.com

Small example and explanation of using DTL in index.html file:

# Extending an HTML template using Django template language
{% extends "base.html" %}
...# Including an HTML template using DTL
{% include "sidebar.html" %}
...# Iterating through the objects inserted in the db table "Post"
# List "post_list" is available because of inheriting from ListView
{% for post in post_list %} # for post in "Post" db table
{% post.title %} # get the title of post

Note: For more details about Django template language, visit here.

Lastly, the structure of the project looks similar like the example below:

|— db.sqlite3
|— mysite
| |— __init__.py
| |— asgi.py
| |— settings.py
| |— urls.py
| |— wsgi.py
|— manage.py
|— blog
| |— __init__.py
| |— admin.py
| |— apps.py
| |— migrations
| |— models.py
| |— tests.py
| |— views.py
| - templates
| |- base.html
| |- index.html
| |- post_detail.html
| |- sidebar.html

Congratulations! 🎉

Assuming all the steps mentioned in this post are followed correctly, the personal blog is now ready to use and looks like in the pictures shown below:

Blog’s main page
Detailed view of a blog post

In addition, feel free to check the source code from my git repo:

Want to learn more?

Some great sources for Django documentation and tutorials, which I’m also inspired by, are mentioned below:

Note: My all-time favorite book about Django 🍨

A short recap

All the necessary steps to create a personal blog from scratch with Python3 and Django3 are covered in this short tutorial.

First, it explains what needs to be installed, and how to create a Django3 app. A short description is written for the structure of a Django app, what files does the app contain and what are their purposes.

Then, proceeding with the database models, migrations and admin built-in interface until the brief explanation of views and rendered templates in Django.

Assuming all the steps are followed in the correct way, the personal blog is ready to use and be customized in your own preferred way!

--

--

Besmire Thaqi
Geek Culture

An experienced Software Engineer based in Munich.