Django Web Framework: How to Create a Django Blog

Django Web Framework: How to Create a Django Blog

 

Django Web Framework

Django is an open-source high-level python web framework that advocates rapid development, clean and pragmatic design. Django is used for building website backends fast. It makes building web applications more quickly and you don't need to know much when using it because it comes with batteries included. 

 

Django Features

 

  • Development is ridiculously fast and complete

    With Django, you take web apps from concepts to completion very fast. Django follows the batteries included principle where everything a developer needs is included as part of the framework. 

  • Security

    Security is a serious concern for web applications. Django takes security seriously and has a pragmatic way of dealing with security concerns to avoid developer mistakes. Django comes with a way to handle user accounts and their passwords. You don't have to put session information inside cookies. 

  • Scalable

    Django is highly scalable. It was written using principles and patterns that encourage the creation of reusable code. You can add a caching server or database server without much concern. 

 

 

How Django came to be.

Django was introduced in 2003 by a team of developers who were in charge of a newspaper website. They realized they can reuse a lot of their code, and started factoring out the reusable code and design principles. The source code evolved rapidly and was open-sourced in 2005.

Ever since its inception, Django has continued to grow and improve. A lot of open source developers helped improve Django.

 

DigitalOcean

DigitalOcean is a cloud services provider based in the united states. They have a wide variety of cloud tools that you can use to deploy your web app easily. We're going to use DigitalOcean when deploying our blog because they offer a 60 days/$100 credit which means you can host your website for free without having to pay a cent.  And it's also easy to deploy a Django app on DigitalOcean.

 

DigitalOcean

 

First, let's Create a Django Blog

We're going to start by creating the Django project on the localhost before we deploy it to DigitalOcean.

 

Prerequisites

  • Python
  • Pip
  • Git
  • Github

 

Note: I'm using ubuntu 20.04 on my laptop so the commands I type might be different from those you have to use. But if it's a Linux based OS, then you're good to go.

 

Create a Django Project

Let install python, pip, and create the project.

mkdir blog && cd blog
sudo apt update && python3-pip python-dev libpq-dev
sudo -H pip3 install --upgrade pip && sudo -H pip2 install virtualenv
virtualenv env

 

What we've done

  • Created a project directory blog
  • Installed python 
  • Installed pip
  • Installed virtualenv
  • created a virtual environment inside the blog directory

 

 

Note that we've not yet created the actual Django project. 

Inside the blog directory, run the following commands to create the Django project and to install all requirements needed.

source env/bin/activate
pip install django pillow django-tinymce gunicorn django-allauth django-crispy-forms python-decouple boto3 django-storages whitenoise psycopg2-binary
django-admin startproject blog .

 

Creating Models

We need one application with one Article model. Models are the database representations of the data.  The model contains the fields and methods to manipulate the data in the fields. Each model you create is mapped to one database table.

Inside your virtual environment, run the following commands to create an article app.

 

python manage.py startapp article

 

Update your settings to add the article application. Open your settings.py file under blog/settings.py.

 

INSTALLED_APPS = [
    .............
    'article.apps.ArticleConfig',
]

 

Now, let's create the articles model. Inside the newly created article application, open the models.py file, and create the model class.

 

from django.db import models
from tinymce.models import HTMLField
from django.utils.translation import gettext_lazy as _
from django.template.defaultfilters import slugify
from django.urls import reverse

# Create your models here.
class Article(models.Model):
    title = models.CharField(_("Title"), max_length=100)
    summary = models.TextField(_("Description"))
    keywords = models.CharField(_("SEO Keywords"), max_length=50)
    body = HTMLField(_("Article body"))
    image = models.ImageField(_("Featured Image"), upload_to="blog/featured")
    live = models.BooleanField(_("Live"), default=False)
    published = models.DateTimeField(_("Date published"), auto_now=False, auto_now_add=False)
    updated = models.DateTimeField(_("Last updated"), auto_now_add=True)
    slug = models.SlugField(max_length=500, unique=True, null=True, blank=True)

    class Meta:
        verbose_name = _("Article")
        verbose_name_plural = _("Articles")

    def save(self, *args, **kwargs):
        string = "{}".format(self.title)
        self.slug = slugify(string)
        super(Article, self).save(*args, **kwargs)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse("article", kwargs={"slug": self.slug})

 

Models Migrations

After creating the article model, we now need to migrate it into a database. 

In your terminal run the following command to make the migrations.

 

python manage.py makemigrations
python manage.py migrate

If you didn't run into errors, then you've successfully created an article table along with all the Django models table.  Let now move into creating sample blog articles. 

 

Create Django SuperUser

Django comes with an admin dashboard and to access it we need a superuser.  

 

python manage.py createsuperuser
python manage.py runserver

 

Go to Localhost and put the username and password you created above. You should be able to see all the tables in the dashboard, except the articles one.

So to add the articles app in the dashboard, open article/admin.py and add the following code. 

 

from django.contrib import admin
from article.models import Article

admin.site.register(Article)

 

Save the file and restart the server. Your changes should now reflect in your admin panel. 

Click add article and put dummy content and save.

 

Configure Django TinyMCE

Our TinyMCE is now yet configured, so open blog/settings.py and add the following code

 

TINYMCE_JS_URL = 'https://cdn.tiny.cloud/1/no-api-key/tinymce/5/tinymce.min.js'
TINYMCE_DEFAULT_CONFIG = {
    "height": "600px",
    "menubar": "file edit view insert format tools image media emoticons toc forecolor backcolor table help",
    "toolbar": 'codesample image numlist bullist preview',
    "plugins": "advlist autolink importcss wordcount media lists emoticons link image toc imagetools charmap print preview textcolor colorpicker codesample anchor searchreplace visualblocks code ",
    "codesample_global_prismjs": True,
    "toc_header": 'div',
    "codesample_languages": [
        { "text": 'HTML/XML', "value": 'markup' },
        { "text": 'JavaScript', "value": 'javascript' },
        { "text": 'CSS', "value": 'css' },
        {"text": "Go", "value": "go"},
        {"text": "Shell", "value": "shell"},
        {"text": "Scala", "value": "scala"},
        {"text": "Scala", "value": "scala"},
        {"text": "Go", "value": "go"},
        { "text": 'PHP', "value": 'php' },
        { "text": 'Ruby', "value": 'ruby' },
        { "text": 'Python', "value": 'python' },
        { "text": 'Java', "value": 'java' },
        { "text": 'C', "value": 'c' },
        { "text": 'C#', "value": 'csharp' },
        { "text": 'C++', "value": 'cpp' },
        { "text": "Vim",  "value": "vim"},
        { "text": "Powershell",  "value": "powershell"},
        {"text":"SQL", "value":"sql"},
        {"text":"sass","value":"sass"},
        {"text":"scss","value":"scss"},
        {"text":"scala","value":"scala"},
        {"text":"r","value":"r"},
        {"text":"jsx","value":"jsx"},
        {"text":"nginx","value":"nginx"},
    ],
}
TINYMCE_SPELLCHECKER = True
TINYMCE_COMPRESSOR = False

 

As you can see, our Django TinyMCE contains a code samples plugin, so you'll be able to add some code inside your blog post.

 

Django Views

Our models are now working and ready for blogging, but we have not yet created our views and URLs. A Django view is a function that takes a request and returns a response, our page.

Open article/views.py and add the following code.

 

from django.db.models import Q
from article.models import Article
from django.views.generic import ListView, DetailView, TemplateView
from django.utils import timezone


class IndexView(ListView):
    template_name = "article/index.html"
    context_object_name = "articles"
    paginate_by = 25
    queryset = Article.objects.all().order_by("-published")
    

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['now'] = timezone.now()
        return context


class ArticleView(DetailView):
    model = Article
    context_object_name = "article"
    template_name = "article/article.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['now'] = timezone.now()
        return context

 

Django Templates

The above views need HTML templates to work. Let create a folder named templates/article and the three-view files we need, base.html, index.html, and article.html inside our article app directory. Or open your terminal and run.

 

mkdir article/templates/article
touch templates/article/base.html
touch templates/article/index.html
touch templates/article/article.html

 

After creating the base.html, index.html, and article.html files inside article/templates/article folder, open the base.html file and add the following code, note that at this moment you can use any CSS library you choose e.g bootstrap. 

 

<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
  {% block seo %}
    <title>{% block title %}Blog title{% endblock title %}</title>
    <meta name="keywords" content="blog keywords">
    <meta name="description" content="Blog description">
  {% endblock seo %}
  <link rel="canonical" href="https://blog.dev{{request.path}}" />
  <meta property="og:site_name" content="blog.dev">
  <meta property="og:type" content="website">
  <meta property="og:title" content="My blog">
  <meta property="og:description" content="Blog description">
  <meta property="og:url" content="https://www.bog.dev/">
  <meta property="og:locale" content="en_US">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:site" content="@blog">
  <meta name="twitter:creator" content="@blog">
  <meta name="twitter:url" content="https://www.blog.dev/">
  <meta name="twitter:title" content="Blog description">
  <meta name="twitter:description" content="Blog description"/>
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.14.0/css/all.css" integrity="sha384-HzLeBuhoNPvSl5KYnjx0BT+WB0QEEqLprO+NBkkk5gbc67FTaL7XIGa2w1L0Xbgc" crossorigin="anonymous">
</head>
<body>
  {% block content %}

  {% endblock content %}
 <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
</body>
</html>

 

You have to edit the meta tags and add your blog details.

Now open your index.html and add the following code. This is going to be the homepage of your blog. It lists all the blog articles.

 

{% extends 'article/base.html' %}
{% load static %}
{% block seo %}
    <title>{% block title %}Blog{% endblock title %}</title>
    <meta name="keywords" content="blog keywords">
    <meta name="description" content="my blog description">
    <meta name="twitter:image" content="{% static '<blog image>' %}">
    <meta property="og:image" content="{% static '<blog image>' %}">
{% endblock seo %}
{% block content %}
<section class="blog-area pt-5 pb-5">
            <div class="container">
                <div class="row">
                    <div class="col-md-12 text-center">
                        <div>
                            <h1>Blog Title</h1>
                        </div>
                    </div>
                </div>
                <div class="row">
                    {% for article in articles %}
                    <div class="col-xl-4 col-lg-4 col-sm-12 col-md-6 mb-30">
                        <div class="white-bg">
                            <div class="blog-thumb">
                                <a href="{% url 'article' article.slug %}">
                                    <img src="{{article.image.url}}" alt="{{article.title}}" />
                                </a>
                            </div>
                            <div class="meta-info">
                                <ul>
                                    <li class="posts-time">{{article.published}}</li>
                                </ul>
                            </div>
                            <div class="blog-content home-blog">
                                <h2 class="blog-title">
                                    <a href="{% url 'article' article.slug %}">{{article.title}}</a>
                                </h2>
                                <p>{{article.summary}}</p>
                            </div>
                            <div class="link-box home-blog-link">
                                <a href="{% url 'article' article.slug %}">Read More</a>
                            </div>
                        </div>
                    </div>
                    {% endfor %}
                </div>
            </div>
        </section>
{% endblock content %}

 

Now we need to have a template for individual blogs. Let's open the article.html file and add the following code.

 

{% extends 'article/base.html' %}
{% load static %}
{% block seo %}
    <title>{% block title %}{{article.title}}{% endblock title %}</title>
    <meta name="keywords" content="{{article.keywords}}">
    <meta name="twitter:image" content="{{article.image.url}}">
    <meta property="og:image" content="{{article.image.url}}">
    <meta name="description" content="{{article.summary}}">
{% endblock seo %}

{% block content %}
 <section>
    <div class="container">
        <div class="row">
            <div class="col-md-10">
                <div>
                    <h1 class="title3">{{article.title}}</h1>
                    <div>
                        <ul>
                            <li>
                                <i class="fas fa-calendar-week"></i>
                                {{article.published}}
                            </li>
                        </ul>
                    </div>
                    <img class="featured-images" src="{{article.image.url}}" alt="{{article.title}}"/>
                    <div>
                        {{article.body|safe}}
                    </div>
                </div>
            </div>
            <div class="col-md-2">
                <!--  Sidebar for ads  !>
            </div>
        </div>
    </div>
</section>
{% endblock content %}

 

Django URLs

Now to complete the equation, we need to create a urls.py inside our articles application. Create urls.py inside the article application and add the following code.

 

from article import views
from django.urls import path


urlpatterns = [
    path('', views.IndexView.as_view(), name="blog"),
    path('<slug>/', views.ArticleView.as_view(), name="article")
]

 

Open your root URLs file inside the blog directory and add the following code. blog/urls.py file.

 

from django.urls import path, include

urlpatterns = [
    ....................................................
    path('', include('article.urls')),
]

 

Now if you run your server and open your blog in the browser, you should be able to see the dummy article you create. 

 

Create the PostgreSQL Database

PostgreSQL database is the most used database with Django. I used it just because it's easier to use on Django than MySQL. So we're going to just use the default SQLite database on localhost and use PostgreSQL on production. 

©2021 Workly. Theo Nga