Setup

Run these commands to setup a base project:

python3 -m venv venv
source venv/bin/activate
pip install django
django-admin startproject mysite .
python manage.py startapp blog
python manage.py migrate
python manage.py runserver

Quickstart

Create a directory called templates in the site root and a directory called blog inside it.

Create a file called index.html inside the blog directory and add these lines to it:

<h1>Blog index</h1>

{% for item in items %}

    <p>{{ item.pk }} {{ item.title}}</p>

{% endfor %}

{% if items.paginator.num_pages > 1 %}

    <div class="pagination">
        {% if items.has_previous %}
            <a href="?page=1">First</a>
            <a href="?page={{ items.previous_page_number }}">Previous</a>
        {% endif %}
        <span>{{ items.number }}</span><span>of</span> <span>{{ items.paginator.num_pages }}</span>
        {% if items.has_next %}
            <a href="?page={{ items.next_page_number }}">Next</a>
            <a href="?page={{ items.paginator.num_pages }}">Last</a>
        {% endif %}
    </div>

{% endif %}

Edit the blog app views.py file and add these lines to it:

from django.shortcuts import render
from .models import Post
from django.core.paginator import Paginator


def index(request):
    posts = Post.objects.all()

    paginator = Paginator(posts, 3)
    page = request.GET.get('page')
    posts = paginator.get_page(page)

    return render(request,
                  'blog/index.html',
                  {'items': posts})

Edit the blog app urls.py file and add these lines to it:

from django.urls import path
from . import views

app_name = 'blog'

urlpatterns = [
    path('', views.index, name='index')
]

Edit the mysite/urls.py file and include the blog app URLs:

from django.contrib import admin
# here
from django.urls import path, include

urlpatterns = [
    # here
    path('blog/', include('blog.urls')),
    path('admin/', admin.site.urls),
]

Edit the blog app models.py file and add these lines to it:

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=255,
                      default='',
                      blank=True
                      )

Edit the mysite/settings.py file and make the following changes:

INSTALLED_APPS = [
    # START
    'blog.apps.BlogConfig',
    # END
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        # START
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        # END
        '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',
            ],
        },
    },
]


STATIC_URL = '/static/'
# START
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
# END

Edit the blog app admin.py file and make the following changes:

from django.contrib import admin
# START
from blog.models import Post
admin.site.register(Post)
# END

Run migrations and create a superuser:

python manage.py makemigrations
python manege.py migrate
python manage.py createsuperuser

Create some post objects:

python manage.py shell
>>> for x in range(0,50):
...     post = Post(title='title')
...     post.save()
...
>>>

Visit /blog/ and you should see something like this:

Re-usable pagination

Create a file called _pagination.html in the templates directory and copy the pagination element from the index.html file to it:

<div class="pagination">
    {% if items.has_previous %}
        <a href="?page=1">First</a>
        <a href="?page={{ items.previous_page_number }}">Previous</a>
    {% endif %}
        <span>{{ items.number }}</span><span>of</span> <span>{{ items.paginator.num_pages }}</span>
    {% if items.has_next %}
        <a href="?page={{ items.next_page_number }}">Next</a>
        <a href="?page={{ items.paginator.num_pages }}">Last</a>
    {% endif %}
</div>

Edit the blog/index.html template file and include the pagination like this:

<h1>Blog index</h1>

{% for item in items %}

    <p>{{ item.pk }} {{ item.title}}</p>

{% endfor %}

{% if items.paginator.num_pages > 1 %}

    <!-- start -->
    {% include '_pagination.html' with items=items %}
    <!-- end -->

{% endif %}

Blue Theme

Edit the templates/blog/index.html file and make it a proper HTML document. Link Font Awesome and pagination CSS in the head section.

<!doctype html>
<!-- start -->
{% load static %}
<!-- end -->
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- start -->
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css"
          integrity="sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay"
          crossorigin="anonymous">
    <link rel="stylesheet"
      href="{% static 'css/pagination.css' %}">
    <!-- end -->
    <title>Document</title>
</head>
<body>

    <h1>Blog index</h1>

    ...

</body>
</html>

Replace the markup in _pagination.html with these lines:

<div class="pagination">
    {% if items.has_previous %}
        <a class="pagination-action" href="?page=1">
            <i class="fa fa-angle-double-left" aria-hidden="true"></i> </a>
        <a class="pagination-action" href="?page={{ items.previous_page_number }}">
            <i class="fa fa-angle-left" aria-hidden="true"></i>
        </a>
    {% endif %}
    {% for num in items.paginator.page_range %}
        {% if items.number == num %}
            <span class="pagination-number pagination-current">{{ num }}</span>
        {% elif num > items.number|add:'-3' and num < items.number|add:'3' %}
            <a class="pagination-number" href="?page={{ num }}">{{ num }}</a>
        {% endif %}
    {% endfor %}
    {% if items.has_next %}
        <a class="pagination-action" href="?page={{ items.next_page_number }}">
            <i class="fa fa-angle-right" aria-hidden="true"></i>
        </a>
        <a class="pagination-action" href="?page={{ items.paginator.num_pages }}">
            <i class="fa fa-angle-double-right" aria-hidden="true"></i>
        </a>1
    {% endif %}
</div>

Create a file called pagination.css file in the static/css directory and add these lines to it:

/* BLUE THEME */

.pagination {
    text-align: center;
    margin-top: 1em;
}

.pagination a {
    text-decoration: none;
}

.pagination-number {
    padding: 0.5em 0.8em;
    border-radius: 2px;
    color: #fff;
    background-color: #6D85C7;
}

.pagination-number:hover,
.pagination-current {
    background-color: #3354AA;
}

.pagination-action {
    margin: 0 0.1em;
    display: inline-block;
    padding: 0.5em 0.5em;
    color: #B9B9B9;
    font-size: 1.3em;
}

.pagination-action:hover,
.pagination-previous,
.pagination-next {
    color: #3354AA;
}

Green Theme

Here is an alternative theme.

_pagination.html:

<div class="pagination">
    {% if items.has_previous %}
        <a class="pagination-action" href="?page=1">
            <i class="fa fa-angle-double-left" aria-hidden="true"></i>
        </a>
        <a class="pagination-action" href="?page={{ items.previous_page_number }}">
            <i class="fa fa-angle-left" aria-hidden="true"></i>
        </a>
    {% endif %}
    <span class="pagination-current">{{ items.number }}</span>
    <span class="pagination-of">of</span>
    <span class="pagination-total">{{ items.paginator.num_pages }}</span>
    {% if items.has_next %}
        <a class="pagination-action" href="?page={{ items.next_page_number }}">
            <i class="fa fa-angle-right" aria-hidden="true"></i> </a>
        <a class="pagination-action" href="?page={{ items.paginator.num_pages }}">
            <i class="fa fa-angle-double-right" aria-hidden="true"></i>
        </a>
    {% endif %}
</div>

pagination.css:

.pagination {
    text-align: center;
    margin-top: 1em;
}

.pagination a {
    text-decoration: none;
}

.pagination-current, 
.pagination-total {
    padding: 0.5em 0.8em;
    border-radius: 2px;
    color: #fff;
    background-color: #30BF61;
}

.pagination-total {
    background-color: #B9B9B9;
}

.pagination-action {
    margin: 0 0.1em;
    display: inline-block;
    padding: 0.5em 0.5em;
    color: #B9B9B9;
    font-size: 1.3em;
}

.pagination-of {
    color: #B9B9B9;
    padding: 0 1em;
}

.pagination-action:hover {
    color: #3354AA;
}