Simple dynamic resume with Django

June 4, 2020

Simple dynamic resume with Django

In this small tutorial, I'm going to show one of the possible variants to create a personal dynamic resume.

Before you begin, please make sure that you have already installed Python 3 on your local machine and you understand how to use the command line to install packages and run Python scripts. Your version can be any, but at least 3.6. Try to run this command to check:

python --version

Disclaimer/note: it is my first real attempt to write something useful, so don't be too judgemental.

Initial setup

So, the first steps in our journey will be set up a virtual environment and install Django package. Please change to the directory where you are going to store your project. It can be anything, for example, my_resume.

To create a new Python virtual environment you can use your IDE or editor or run this command in the terminal:

python -m venv venv

Next, you need to activate it. For Linux or Mac command will be:

source ./venv/bin/activate

If you are on Windows 10 and use PowerShell command may look like this:

& .\venv\Scripts\Activate.ps1

After creating and activating the virtual environment let's install the actual Django package:

pip install Django~=3.0.6

and check if everything is ok by running this command:

python -c 'import django; print(django.__version__)'

as an output, you should see the version of the installed framework, for example, 3.0.6. Now you are ready to move next.

Basic project

Django uses projects and applications as building blocks for sites. Project is a Python module where you store base settings, main URL map and common templates and static files related to the entire site (project). Applications, from the other side, are small packages which contain functionality related to one part of the project, for example, blog (posts), users, static pages etc.

So let's create our project. I'm going to use the current directory as the root of the project.

django-admin startproject my_resume .

After running that command your directory should contain project package, manage script and virtual environment:

├── venv
└── my_resume

Now you can start a development server for the first time:

python runserver

The server should start on port 8000 by default. You can point your browser to the address and see the Django default page.

An resume app

It's time to create our first application which will hold actual logic for working with resume.

Start a new Django application with the command:

python startapp resume

A new python package `resume` will be created and it will contain initial files (Python modules) common for all Django packages (applications).

Next, we need to register our new application in settings. Open file `my_resume/` and update the `INSTALLED_APPS` list:

    # ...


Because we are going to create a dynamic resume, these data should be stored somewhere. And, fortunately, Django can help us with this. By default, it provides functionality to work with databases as data storage. And right out of the box Django supports working with SQLite 3.

Let's take a look at my_resume/

# Database

    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),

This shows that we already have a default data source and database with the name db.sqlite3 will be stored in the root of our project.

The main concept of using databases is in creating models for each table and then let Django manage migration and all necessary steps to update the schema and structure of our database.

Now, let's open resume/ file add our model to it:

from django.db import models

class Section(models.Model):
    position = models.SmallIntegerField(
        help_text="Relative position of this section on a resume page, stating from 1 at the most top",
    title = models.CharField(max_length=150, unique=True)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ("position",)
        verbose_name = "resume section"
        verbose_name_plural = "resume sections"

    def __str__(self):
        return self.title

    def __repr__(self):
        return f"<Section id={} title={self.title}>"

First of all, we are importing module models from django.db package. This module contains field types, object managers and other functions needed to interact with databases. Next, we are defining our model which will be representing the corresponding table in the database. Each section in our resume will have title, content and ordering position on the resulting page.

After we defined model we need to tell Django to write a migration to be able to create a corresponding table(s) in the database. To do this we are using one of the commands. So return to your terminal and run:

python makemigrations

A new file resume/migrations/ should be created. You can explore it and see how Django writes migrations.

Next, we need to update our database by running migrate command:

python migrate

Among all other migrations you should see that our newly created migration was applied too:

Applying resume.0001_initial... OK

Now, we are ready to go further.

Admin integration

Before we start using our data to build an actual page we need a place where we cat create such data. Luckily for us, Django provides automatic admin generation. Let's tell Django how we want it to be.

Open file resume/ and add the next lines to it:

from django.contrib import admin

from .models import Section

class SectionAdmin(admin.ModelAdmin):
    date_hierarchy = "created_at"
    list_display = (
    list_filter = ("created_at",)
    search_fields = ("title",)
    readonly_fields = ("created_at", "updated_at")

Here, we are importing the admin module from django.contrib package, our Section model and then register custom admin class where we guide Django what to show on the list page, which fields will be read-only.

That's all that we need to have nice formatted admin pages for creating, editing and deleting sections of a resume.

But before we can use admin interface we need to have at least one user in our database with access to the admin area. The easiest way to do so is to use manage command. Run in terminal:

python createsuperuser

Then we can run dev server again and navigate to, log in with our credentials and open the Resume sections page. Feel free to add some sections to your resume such as experience, goals, education and so on.

Template and view

Now, when we have some content it's time to show them fashionably.

To show any page to users, Django uses views and templates. The view is a python function or a class, template - HTML code which framework is returning as a response. Templates can be just static text or contain dynamic data which view is set as a context for template rendering.

For this particular resume page, I prefer to use class-based view derived from Django base ListView class. Open file resume/ and add our new view:

from django.views.generic import ListView

from .models import Section

class ResumePage(ListView):
    model = Section
    context_object_name = "resume_sections"
    template_name = "resume.html"
    queryset = Section.objects.all()

Here we are telling Django that it should use resume.html template, select all resume sections from the database and put them in the resume_section context variable to use within the template.

Now, let's create that template. Create and open file resume/templates/resume.html:

<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Mark Bishop</title>
    <h1>Mark Bishop</h1>
    <h3>Web Software Developer</h3>


        {% for section in resume_sections %}
            <dt><strong>{{ section.title }}</strong></dt>
            <dd>{{ section.content | safe }}</dd>
        {% endfor %}

Let's add our resume page as the main page for the site. Open file my_resume/ and replace existing content with:

from django.contrib import admin
from django.urls import path

from resume.views import ResumePage

urlpatterns = [
    path('', ResumePage.as_view(), name='resume'),

Now you can visit and check your newly created resume page. Make sure that your dev server is up and running.


It's just one small step on your way to building big websites. Next, you may want to extend your work, for example, find a nicer template for resume on the Internet and use it, add images such as your photo, etc. Don't hesitate to change something, add new features. It may be a good idea to host your project somewhere, for example on Heroku, DigitalOcean, Linode, Amazon AWS, etc.

The door is open, just go inside!


© 2020 Serhii Diachok. All rights reserved.