How I Built a Resume Builder with Django and Fauna
Tags: fauna, python, programming, django
Published: 2021-04-02 09:24:04

_Authored in connection with the [Write With Fauna](https://fauna.com/blog/write-with-fauna) program._

For some time now, I have been learning about [Fauna](https://fauna.com) and exploring its serverless database management system by building various web applications with it. In this tutorial, I will walk you through a step-by-step guide that shows how I made a resume builder with Django and [Fauna](https://fauna.com).

# Prerequisites

To fully understand this tutorial, you are required to have the following in place:


* Python 3.7 or newer.
* Basic understanding of Fauna.
* Basic understanding of Django.
* A text editor.

# Setting Up Fauna Database

To make use of [Fauna](https://fauna.com), I had to set up required collections, indexes, and API keys. Below are the steps I took to achieve this:

## Creating the Database

I created a database on Fauna’s dashboard for the project. To do this, [login to your dashboard](https://dashboard.fauna.com/accounts/register?utm_source%3DDevTo%26utm_medium%3Dreferral%26utm_campaign%3DWritewithFauna_DjangoResume_Ochuko), click the `New Database` button and provide the required information.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6xwvsi61ep45ihuwo0ac.png)

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xcpq6vgvlcmxco8vdjei.png)

## Creating the Collections

I needed to create collections for storing our data in Fauna. Collections are like tables in a standard database system. I created two collections for the resume builder project, which are `Users` (storing registered users) and `Resume_Info` collection (storing information used to generate the user’s resume).

To create collections in Fauna, navigate to the `Collections` tab in Fauna’s dashboard side menu, click on the `New Collection` button and provide the information required as seen in the images below:

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g0q7910q1ldyh9jcp5oa.png)![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ay1g510yebc5znw7d6cz.png)

The `TTL` field is where you specify how long you want the data in the respective collections to last, while the `History Days` stores historical records. For this project, I used the default value of 30 for ` History days` and left the `TTL` blank.

## Creating the Fauna Indexes

I needed to create indexes for browsing through data in the database collections. I created two indexes for this project, one for each collection named `users_index` and `resume_index`. I then set appropriate `Terms` for them.

To create an index, navigate to the `Indexes` tab in Fauna’s dashboard side menu, click on the `New Index` button and provide the information required as seen in the images below: 

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xzt38tiqtfwbchifum7r.png)

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fuqcnpikkfw5neeb8dgx.png)

For the `users_index`, I set the connected collection to `Users`, and the `Terms` for browsing data with this index is the `username` field. The `Terms` are fields in the collection that Fauna will match when querying a collection with an index.

For the `resume_index`, I set the connected collection to `Resume_Info` and the `Terms` to `user`. Tick the unique checkbox for both indexes before saving to specify that all data queried is unique.

## Creating the Database Security Key

To enable Django to interact with [Fauna](https://fauna.com), a secret key is required by the [Fauna Driver](https://github.com/fauna/faunadb-python). To do this, navigate to the `Security` tab in Fauna’s dashboard side menu, click on the `New Key` button and provide the information required as seen in the images below:

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m60mofrzc3egeh1azg5v.png)

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8uaszta3xohpsi2zdm5r.png)

After generating the secret key, you will be presented with a screen like the one above (hidden here as “SECRET_KEY” for privacy). Copy your secret key from the dashboard and save it somewhere you can easily retrieve it for later use.

# Creating The Resume Builder Django Project

To install Django and Fauna, simply run the command below:

```

pip install django

pip install faunadb

```

At this point, I created the Django project using the commands below:

```

# create the django project

django-admin startproject RESUME_BUILDER

# change directory to the django project

cd RESUME_BUILDER

# create the django app

django-admin startapp App

```

In the command above, I first created a project called `RESUME_BUILDER`, then changed the directory to the Django project. In the project directory, I created a new app called `App`.

I then edited my `settings.py` file in my project folder and added the following code. Navigate to the `RESUME_BUILDER` directory and edit our `settings.py` file by adding our app to the list of installed apps as seen below:

```python

INSTALLED_APPS = [

 'django.contrib.admin',

 'django.contrib.auth',

 'django.contrib.contenttypes',

 'django.contrib.sessions',

 'django.contrib.messages',

 'django.contrib.staticfiles',

 'App'

]

```

I also defined the static and media paths at the end of the `settings.py` file as seen in the code below:

```python

STATIC_URL = '/static/'

STATIC_ROOT=os.path.join(BASE_DIR, 'static')

MEDIA_ROOT =os.path.join(BASE_DIR, 'media')

MEDIA_URL = '/media/'

```

Next, I edited the `urls.py` file in the project folder with the code below, which links it to my app’s URLs.

```python

from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.contrib.staticfiles.urls import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include("App.urls")),


]
urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

```

Finally, I made migrations to save and migrate all settings to the database. Run the code below in your command-line to make migrations.

```

python manage.py migrate

```

## The Django Project Structure

I needed to structure the Django project in a particular way that follows Django’s rules and will make it easy to work with during this tutorial. To do this, navigate to the `App` folder in your project, then create a new file, `urls.py`.In the `App` folder, create two new folders; `templates` and `static`. The template folder will house our HTML files, while the static folder will house our CSS, Javascript, and other static files. To do this, run the command below on your command-line.

```

#change directory to our App

cd App

mkdir templates

mkdir static

```

These commands will structure the `App` folder as seen in the image below:

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8m0ccp5a9kacyqz2jkzg.png)

## Defining the URL routes

A `urls.py` in the `App` folder will contain all defined URL routes for our app. To do this, create a `urls.py` file and add the code as seen below:

```python

from django.conf import settings
from django.conf.urls.static import static
from django.urls import path, include
from . import views

app_name = "App"

urlpatterns = [
    path("", views.login, name="login"),
    path("login", views.login, name="login"),
    path("register", views.register, name="register"),
    path("index", views.index, name="index"),
    path("create-resume", views.create_resume, name="create-resume"),
    path("resume", views.resume, name="resume"),


]

```

# Building the User Interface

The user interface entails all the HTML, CSS, and Javascript files required to build a user-friendly interactive web application.

## Creating the Static Files

I created two new files in the `static` folder, `styles.css` and `script.js`. I then updated them with their respective CSS and Javascript codes as seen in the Github Gist [here](https://gist.github.com/Chukslord1/807f5ed373ce245a87b6ef405a73516d).

## The Login Page

Users need to be authenticated to access the web application. In the `templates` folder, I created a new file named `login.html` and updated it with the code below:

```html

{% load static %}

<!DOCTYPE html>

<html lang="en">

 <head>

 <meta charset="utf-8"/>

 <title>

 Fauna Resume Builder

 </title>

 <link href="{% static './style.css' %}" rel="stylesheet"/>

 </head>

 <body>

 <!-- partial:index.partial.html -->

 <div id="javascript_header">

 </div>

 <form method="POST">

 {% csrf_token %}

 <div class="form__header">

 <h1>

 Login/Sign In

 </h1>

 <p>

 Enter your login details below.

 </p>

 {% csrf_token %}

<ul class="messages">

 {% for message in messages %}

 <li{% if message.tags %} class="{{ message.tags }}"{% endif %} style="color:red;">{{ message }}</li>

 {% endfor %}

</ul>

 </div>

 <div class="form-group">

 <label for="name">

 Username

 <span>

 *

 </span>

 </label>

 <input id="username" name="username" type="text"/>

 <div class="error" id="name__error">

 </div>

 </div>

 <div class="form-group">

 <label for="password">

 Password

 <span>

 *

 </span>

 </label>

 <input id="password" name="password" type="password"/>

 </div>

 <div class="line-break">

 </div>

 <input id="login" type="submit" value="Login"/>

 Don't have an account? <a href="register">Sign Up</a>

 </form>

 <!-- partial -->

 <script src="{% static './script.js' %}">

 </script>

 </body>

</html>

```

## The Register Page

For users to successfully authenticate on the login page, they need to create login details on the register page. To achieve this, in the templates folder, I created a `register.html` file and added the below HTML code:

```html

{% load static %}

<!DOCTYPE html>

<html lang="en">

 <head>

 <meta charset="utf-8"/>

 <title>

 Fauna Resume Builder

 </title>

 <link href="{% static './style.css' %}" rel="stylesheet"/>

 </head>

 <body>

 <!-- partial:index.partial.html -->

 <div id="javascript_header">

 </div>

 <form method="POST">

 {% csrf_token %}

 <div class="form__header">

 <h1>

 Register/Sign Up

 </h1>

 <p>

 Enter your login details below.

 </p>

 </div>

 <div class="form-group">

 <label for="name">

 Username

 <span>

 *

 </span>

 </label>

 <input id="username" name="username" type="text"/>

 <div class="error" id="name__error">

 </div>

 </div>

 <div class="form-group">

 <label for="email">

 Email

 <span>

 *

 </span>

 </label>

 <input id="email" name="email" type="email"/>

 <div class="error" id="name__error">

 </div>

 </div>

 <div class="form-group">

 <label for="password">

 Password

 <span>

 *

 </span>

 </label>

 <input id="password" name="password" type="password"/>

 </div>

 <div class="line-break">

 </div>

 <input id="register" type="submit" value="Register"/>

 Already have an account? <a href="login">Sign In</a>

 </form>

 <!-- partial -->

 <script src="{% static './script.js' %}">

 </script>

 </body>

</html>

```

## The Dashboard Page

This page is where users can access the functionalities of the resume builder easily. To achieve this, I created an `index.html` file in the `templates` folder and added the below HTML code:

```html

{% load static %}

<!DOCTYPE html>

<html lang="en">

 <head>

 <meta charset="utf-8"/>

 <title>

 Fauna Resume Builder

 </title>

 <link href="{% static './style.css' %}" rel="stylesheet"/>

 </head>

 <body>

 <!-- partial:index.partial.html -->

 <div id="javascript_header">

 </div>

 <form>

 <div class="form__header">

 <h1>

 Build Your Resume

 </h1>

 <p>

 Dashboard

 </p>

 </div>

 <div class="line-break">

 </div>

 <a class="button" href="create-resume"> Create/Edit Resume</a>

 <div class="line-break">

 </div>

 <a class="button" href="resume"> View Resume</a>

 <div class="line-break">

 </div>

 <a class="button" style="background-color:red;" href="login"> Logout </a>

 </form>

 <!-- partial -->

 <script src="{% static './script.js' %}">

 </script>

 </body>

</html>

```

## The Create Resume Page

On this page, users submit their resume info for their resume to be generated. To achieve this page, I created a `create-resume.html` page in the `templates` folder and added the code below:

```html

{% load static %}

<!DOCTYPE html>

<html lang="en">

 <head>

 <meta charset="utf-8"/>

 <title>

 Fauna Resume Builder

 </title>

 <link href="{% static './style.css' %}" rel="stylesheet"/>

 </head>

 <body>

 <!-- partial:index.partial.html -->

 <div id="javascript_header">

 </div>

 <form method="POST">

 {% csrf_token %}

 <ul class="messages">

 {% for message in messages %}

 <li{% if message.tags %} class="{{ message.tags }}"{% endif %} style="color:red;">{{ message }}</li>

 {% endfor %}

 </ul>

 <div class="form__header">

 <h1>

 Build Your Resume

 </h1>

 <p>

 Enter the fields below to generate a resume file.

 </p>

 </div>

 <h2>

 Personal Details

 </h2>

 <div class="form-group">

 <label for="name">

 Full Name

 <span>

 *

 </span>

 </label>

 <input id="name" name="name" value="{{resume_info.full_name}}" type="text"/>

 <div class="error" id="name__error">

 </div>

 </div>

 <div class="form-group">

 <label for="address">

 Address

 </label>

 <input id="address" name="address" value="{{resume_info.address}}" type="text"/>

 </div>

 <div class="form-group">

 <label for="phone">

 Phone

 </label>

 <input id="phone" name="phone" value="{{resume_info.phone}}" type="text"/>

 </div>

 <div class="form-group">

 <label for="email">

 Email

 <span>

 *

 </span>

 </label>

 <input id="email" name="email" value="{{resume_info.email}}" type="email"/>

 <div class="error" id="email__error">

 </div>

 </div>

 <div class="form-group">

 <label for="about">

 About You

 </label>

 <textarea id="about" name="about" placeholder="{{resume_info.about_you}}"></textarea>

 </div>

 <div class="form-group">

 <label for="career">

 Career Objectives

 </label>

 <textarea id="career" name="career" placeholder="{{resume_info.career}}"></textarea>

 </div>

 <div class="form-group">

 <label for="education">

 Education

 </label>

 <textarea id="education" name="education" placeholder="{{resume_info.education}}"></textarea>

 </div>

 <div class="line-break">

 </div>

 <h2>

 Work Experience

 </h2>

 <h3>

 Most Recent Job

 </h3>

 <div class="form-date-group">

 <div class="form-group">

 <label for="job-1__start">

 Start Date

 </label>

 <input id="job-1__start" name="job-1__start" value="{{resume_info.job_1__start}}" type="date"/>

 </div>

 <div class="form-group">

 <label for="job-1__end">

 End Date

 </label>

 <input id="job-1__end" name="job-1__end" value="{{resume_info.job_1__end}}" type="date"/>

 </div>

 </div>

 <div class="form-group">

 <label for="job-1__details">

 Position Details

 </label>

 <textarea id="job-1__details" name="job-1__details" placeholder="{{resume_info.job_1__details}}"></textarea>

 </div>

 <div class="line-break">

 </div>

 <h3>

 Past Job

 </h3>

 <div class="form-date-group">

 <div class="form-group">

 <label for="job-2__start">

 Start Date

 </label>

 <input id="job-2__start" name="job-2__start" value="{{resume_info.job_2__start}}" type="date"/>

 </div>

 <div class="form-group">

 <label for="job-2__end">

 End Date

 </label>

 <input id="job-2__end" name="job-2__end" value="{{resume_info.job_2__end}}" type="date"/>

 </div>

 </div>

 <div class="form-group">

 <label for="job-2__details">

 Position Details

 </label>

 <textarea id="job-2__details" name="job-2__details" placeholder="{{resume_info.job_2__details}}"></textarea>

 </div>

 <div class="line-break">

 </div>

 <h3>

 Another Past Job

 </h3>

 <div class="form-date-group">

 <div class="form-group">

 <label for="job-3__start">

 Start Date

 </label>

 <input id="job-3__start" name="job-3__start" value="{{resume_info.job_3__start}}" type="date"/>

 </div>

 <div class="form-group">

 <label for="job-3__end">

 End Date

 </label>

 <input id="job-3__end" name="job-3__end" value="{{resume_info.job_3__end}}" type="date"/>

 </div>

 </div>

 <div class="form-group">

 <label for="job-3__details">

 Position Details

 </label>

 <textarea id="job-3__details" name="job-3__details" placeholder="{{resume_info.job_3__details}}"></textarea>

 </div>

 <div class="line-break">

 </div>

 <div class="form-group">

 <label for="references">

 References

 </label>

 <textarea id="references" name="references" placeholder="{{resume_info.references}}"></textarea>

 </div>

 <div class="line-break">

 </div>

 <input type="submit" value="Submit Info"/>

 <br>

 <a class="button"style="background-color:red;" href="index">Back to home</a>

 </form>

 <!-- partial -->

 <script src="{% static './script.js' %}">

 </script>

 </body>

</html>

```

## The Resume Page

The resume page is where the generated resume generated would be displayed for the user to view. To achieve this page, I created a new file `resume.html` and added the code below:

```html

<html>

<head>

 <title>{% if resume_info.full_name %}{{resume_info.full_name}}'s Resume {% endif %}</title>

 <style>

@import url('https://fonts.googleapis.com/css?family=Poppins:400,600&display=swap');

body {

 font-family: 'Poppins', sans-serif;

 background: #fafafa;

 color: rgba(0,0,0,0.75);

}

h1 {

 color: rgba(0,0,0,0.9);

}

h1, p {

 box-sizing: border-box;

 margin: 0px;

 padding: 0px 24px;

}

.line-break {

 width: 100%;

 height: 1px;

 margin: 16px auto;

 border-bottom: 1px solid #eee;

}

.resume {

 border-radius: 8px;

 box-sizing: border-box;

 display: flex;

 flex-direction: column;

 max-width: 800px;

 margin: 48px auto;

 padding: 16px 0px;

 background: white;

 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02), 0 1px 2px rgba(0, 0, 0, 0.14);

}

.resume-group {

 box-sizing: border-box;

 padding: 8px 0px;

 width: 100%;

 display: flex;

 border-left: 3px solid transparent;

 transition: 0.2s;

}

.resume-group:hover {

 border-left: 3px solid #64FFDA;

}

.left-col {

 width: 35%;

}

.right-col {

 width: 65%;

}

.instructions {

 opacity: 0.5;

 text-align: center;

 font-size: 0.8rem;

 margin: 16px auto;

}

</style>

</head>

<body>

 <div class="resume">

 {% if resume_info.full_name %}

 <h1>{{resume_info.full_name}}</h1>

 {% endif %}

 {% if resume_info.email %}

 <p>{{resume_info.email}}</p>

 {% endif %}

 {% if resume_info.phone %}

 <p>{{resume_info.phone}}</p>

 {% endif %}

 {% if resume_info.address %}

 <p>{{resume_info.address}}</p>

 {% endif %}

 <div class="line-break"></div>

 {% if resume_info.about_you%}

 <div class="resume-group">

 <div class="left-col"><p>ABOUT ME</p></div>

 <div class="right-col">

 <p>{{resume_info.about_you}}

</p>

</div>

</div>

{% endif %}

{% if resume_info.career %}

<div class="resume-group"><div class="left-col">

 <p>CAREER OBJECTIVES</p>

</div>

<div class="right-col">

 <p>{{resume_info.career}}</p>

</div>

</div>

{% endif %}

{% if resume_info.education %}

<div class="resume-group">

 <div class="left-col">

 <p>EDUCATION</p>

 </div>

 <div class="right-col">

 <p>{{resume_info.education}}</p>

</div>

</div>

{% endif %}

<div class="resume-group">

 <div class="left-col">

 <p>EMPLOYMENT EXPERIENCE</p>

 </div>

 <div class="right-col">

 <p></p>

 </div>

</div>

{% if resume_info.job_1__start %}

<div class="resume-group">

 <div class="left-col">

 <p>{{resume_info.job_1__start}} to {{resume_info.job_1__end}}</p>

 </div>

 <div class="right-col">

 <p>{{resume_info.job_1__details}}

</p>

</div>

</div>

{% endif %}

{% if resume_info.job_2__start %}

<div class="resume-group">

 <div class="left-col">

 <p>{{resume_info.job_2__start}} to {{resume_info.job_2__end}}</p>

 </div>

 <div class="right-col">

 <p>{{resume_info.job_2__details}}

</p>

</div>

</div>

{% endif %}

{% if resume_info.job_3__start %}

<div class="resume-group">

 <div class="left-col">

 <p>{{resume_info.job_3__start}} to {{resume_info.job_3__end}}</p>

 </div>

 <div class="right-col">

 <p>{{resume_info.job_3__details}}

</p>

</div>

</div>

{% endif %}

<div class="resume-group">

 <div class="left-col">

 <p>REFERENCES</p>

 </div>

 <div class="right-col">

 <p>{% if resume_info.references %}{{resume_info.references}}{% else %}Available upon request{% endif %}</p>

 </div>

</div>

</div>

<div class="instructions">Ctrl + P and "Save As PDF" to make a copy of this resume</div>

</body>

</html>

```

# Building the Functionalities

We would now be focusing on how I created the app logic. In Django, the logic is built majorly in the `views.py` file in the `App` folder.

## Importing the Required Modules

Firstly, I imported the modules required for this project to work in the `views.py` file as seen in the code below:

```python

from django.shortcuts import render,redirect
from django.contrib import messages
from django.http import HttpResponseNotFound
from faunadb import query as q
import pytz
from faunadb.objects import Ref
from faunadb.client import FaunaClient
import hashlib
import datetime

```

## Initializing the FQL Client and Index

To allow the python app to interact with [Fauna](https://fauna.com) easily, I needed to initialize the client and indexes using the secret key I saved earlier. To do this, I added the code below to the `views.py` file.

```python

client = FaunaClient(secret="SECRET_KEY")

indexes = client.query(q.paginate(q.indexes()))

```

## The Login Functionality

To create the logic for the login page, I added the code below to my `views.py`as seen below:

```python

def login(request):
    if request.method == "POST":
        username = request.POST.get("username").strip().lower()
        password = request.POST.get("password")

        try:
            user = client.query(q.get(q.match(q.index("users_index"), username)))
            if hashlib.sha512(password.encode()).hexdigest() == user["data"]["password"]:
                request.session["user"] = {
                    "id": user["ref"].id(),
                    "username": user["data"]["username"]
                }
                return redirect("App:index")
            else:
                raise Exception()
        except:
            messages.add_message(request, messages.INFO,"You have supplied invalid login credentials, please try again!", "danger")
            return redirect("App:login")
    return render(request,"login.html")


```

In the code above, I checked if a POST request was received. If one was received, I collected the required data expected to be obtained from the POST request, which is the username and the password of the user. I then used the data stored in the username variable as a matching parameter for the FQL client to utilize in querying the `Users` collection for a user matching the data in the username field using the `users_index` index. If the user existed, I checked if the password for that users matched the one provided. If the passwords matched, the user is successfully authenticated, and the username is stored in the session. However, if the user does not exist or the passwords provided don’t match, then a message, “You have supplied invalid login credentials” is rendered. 

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1pv2fitzmkwg3sgz2nm.png)

## The Register Functionality

To create the logic for the register page, I added the code below to my `views.py`as seen below:

```python

def register(request):
    if request.method == "POST":
        username = request.POST.get("username").strip().lower()
        email = request.POST.get("email").strip().lower()
        password = request.POST.get("password")

        try:
            user = client.query(q.get(q.match(q.index("users_index"), username)))
            messages.add_message(request, messages.INFO, 'User already exists with that username.')
            return redirect("App:register")
        except:
            user = client.query(q.create(q.collection("Users"), {
                "data": {
                    "username": username,
                    "email": email,
                    "password": hashlib.sha512(password.encode()).hexdigest(),
                    "date": datetime.datetime.now(pytz.UTC)
                }
            }))
            messages.add_message(request, messages.INFO, 'Registration successful.')
            return redirect("App:login")
    return render(request,"register.html")

```

In the code above, I checked if a POST request was received. If one was received, I then collected the required data expected to be obtained from the POST request, which is the user’s username, email, and password. I then used the data stored in the username as a matching parameter for the FQL client to utilize in querying the `Users` collection for a user matching the data in the username field using the `users_index` index. If the user existed, a message, “ User already exists with that username” is rendered. However, if there is no match in the database, an account with the required info is created in the database by making a query to the `Users` collection using the FQL client.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ck2tgxbxke9vk5aqj3q.png)

## The Dashboard

For the dashboard, no logic is required. I simply rendered the “index.html” file with the code below:

```python

def index(request):
    return render(request,"index.html")

```

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hpfqcfim9fmmtzglzhel.png)

## 

## The Create Resume Functionality

I added the code seen below to the `views.py` file to implement the resume creation logic for the create resume functionality.

```python

def create_resume(request):
    if request.method=="POST":
        username=request.session["user"]["username"]
        full_name=request.POST.get("name")
        address=request.POST.get("address")
        phone=request.POST.get("phone")
        email=request.POST.get("email")
        about_you=request.POST.get("about")
        education=request.POST.get("education")
        career=request.POST.get("career")
        job_1__start=request.POST.get("job-1__start")
        job_1__end=request.POST.get("job-1__end")
        job_1__details=request.POST.get("job-1__details")
        job_2__start=request.POST.get("job-2__start")
        job_2__end=request.POST.get("job-2__end")
        job_2__details=request.POST.get("job-2__details")
        job_3__start=request.POST.get("job-3__start")
        job_3__end=request.POST.get("job-3__end")
        job_3__details=request.POST.get("job-3__details")
        references=request.POST.get("references")
        try:
            resume = client.query(q.get(q.match(q.index("resume_index"), username)))
            quiz = client.query(q.update(q.ref(q.collection("Resume_Info"),resume["ref"].id()), {
                "data": {
                    "user":username,
                    "full_name": full_name,
                    "address": address,
                    "phone": phone,
                    "email":email,
                    "about_you":about_you,
                    "education":education,
                    "career":career,
                    "job_1__start":job_1__start,
                    "job_1__end":job_1__end,
                    "job_1__details":job_1__details,
                    "job_2__start":job_2__start,
                    "job_2__end":job_2__end,
                    "job_2__details":job_2__details,
                    "job_3__start":job_3__start,
                    "job_3__end":job_3__end,
                    "job_3__details":job_3__details,
                }
            }))
            messages.add_message(request, messages.INFO, 'Resume Info Edited Successfully. Download Resume Now')
            return redirect("App:create-resume")
        except:
            quiz = client.query(q.create(q.collection("Resume_Info"), {
                "data": {
                    "user":username,
                    "full_name": full_name,
                    "address": address,
                    "phone": phone,
                    "email":email,
                    "about_you":about_you,
                    "education":education,
                    "job_1__start":job_1__start,
                    "job_1__end":job_1__end,
                    "job_1__details":job_1__details,
                    "job_2__start":job_2__start,
                    "job_2__end":job_2__end,
                    "job_2__details":job_2__details,
                    "job_3__start":job_3__start,
                    "job_3__end":job_3__end,
                    "job_3__details":job_3__details,
                }
            }))
            messages.add_message(request, messages.INFO, 'Resume Info Saved Successfully. Download Resume Now')
            return redirect("App:resume")
    else:
        try:
            resume_info = client.query(q.get(q.match(q.index("resume_index"), request.session["user"]["username"])))["data"]
            context={"resume_info":resume_info}
            return render(request,"create-resume.html",context)
        except:
            return render(request,"create-resume.html")


```

In the code above, I checked if a POST request was received. If one was received, I collected the required data from it and used it to generate the user’s resume. I then checked if the user has already submitted resume information earlier by using the username of the user stored in the session as a matching parameter for the FQL client to utilize in querying the database for data that match the user field of the `Resume_Info` collection. If the user didn’t have any resume information saved before, then documents will be created using the resume information collected. However, if the user has saved his/her resume information earlier, then the resume info is updated using the new resume_info provided. I also rendered the resume info data for the user in the respective field to the create resume page using context.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u0j5jsk3ieger9f2tsup.png)![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i79w2skgm45uvaxn15h7.png)![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/za5su8ba8u27jnd1y723.png)![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nve4bpix9kbvsj2xdtkl.png)

## The Resume Page Functionality

The only functionality this page has is to render already saved data on the resume page.

I achieved this by making a query using the FQL to get the resume info for the current user by using the username as a match for the user field in the `Resume_Info` collection. I then passed the data retrieved to context which will be rendered on the resume page. To achieve this I added the code below and add to my `views.py` file as seen below:

```python

def resume(request):
    try:
        resume_info = client.query(q.get(q.match(q.index("resume_index"), request.session["user"]["username"])))["data"]
        context={"resume_info":resume_info}
        return render(request,"resume.html",context)
    except:
        return render(request,"resume.html")

```

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1rm78he75x18bffsawuo.png)

Finally, I succeeded in building my resume builder web application. If you followed through with this tutorial, run your article by executing the below command.

```

python manage.py runserver

```

You can now view your application on your [localhost](http://127.0.0.1:8000/)

# Conclusion

In this article, I walked you through a step-by-step guide showing how I built a resume builder using [Fauna](https://fauna.com/) and Django. We saw how easy it is to integrate Fauna into a Python/Django application and got our hands dirty by exploring some of its core features and functionalities.

The source code of the resume builder application is available on [Github](https://github.com/Chukslord1/FAUNA_RESUME_BUILDER), and you can access a live demo [here](http://faunaresumebuilder.larridscare.com.ng/). If you have any questions, don't hesitate to contact me on Twitter: [@](https://twitter.com/LordChuks3)[LordChuks3](https://twitter.com/LordChuks3).