How to build a JSON formatted resume API with Django, and ElephantSQL

Anozie Baron Chibuikem
6 min readMar 4, 2022
picture of json resume response

In this article I will show you how to build a resume json formatted application with Django and ElephantSQL(runs postgres under the hood).
Hopefully you know how to create a Django project and start/register a new application in your project as I will be skipping that part.

I will assume that your project is called “ResumeJson” and the new app you created is called “resume”.
Create a “requirement.txt” file in your project root directory and add the following.

Django==4.0.2
psycopg2-binary==2.9.1
gunicorn==20.0.4
django_phonenumber_field==6.1.0
phonenumbers==8.12.44

Install the dependencies by running , “pip install -r requirements.txt”.
I will assume this is your project folder structure at this point

├── manage.py
└── resume
└── ResumeJson
└── requirements.txt
└── db.sqlite3

Inside the resume application, add the following in the models.py

from phonenumber_field.modelfields import PhoneNumberField
from django.db import models
from django.contrib.postgres.fields import ArrayField
class Location(models.Model):
city = models.CharField(max_length=50, null=True, blank=True)
state = models.CharField(max_length=50, null=True, blank=True)
country_code = models.CharField(max_length=5, null=True, blank=True)
country = models.CharField(max_length=25, null=True, blank=True)
postal_code = models.CharField(max_length=50, null=True, blank=True)

def __str__(self):
return self.country
class SocialProfile(models.Model):
network = models.CharField(max_length=50, null=True, blank=True)
username = models.CharField(max_length=50, null=True, blank=True)
url = models.URLField(null=True, blank=True)
def __str__(self):
return self.network
class WorkHistory(models.Model):
company = models.CharField(max_length=100, blank=True)
position = models.CharField(max_length=100, blank=True)
website = models.URLField(null=True, blank=True)
start_date = models.DateField(null=True, blank=True)
end_date = models.DateField(null=True, blank=True)
company_summary = models.CharField(max_length=255, null=True, blank=True)
highlight = models.TextField(null=True, blank=True)
def __str__(self):
return self.company
class Education(models.Model):
institution = models.CharField(max_length=100, null=True, blank=True)
course_enrolled = models.CharField(max_length=100, null=True, blank=True)
study_type = models.CharField(max_length=100, null=True, blank=True)
start_date = models.DateField(null=True, blank=True)
end_date = models.DateField(null=True, blank=True)
def __str__(self):
return self.institution
class Publication(models.Model):
title = models.CharField(max_length=255, null=True, blank=True)
published_on = models.CharField(max_length=100, null=True, blank=True)
date_published = models.DateField(null=True, blank=True)
website = models.URLField(null=True, blank=True)
def __str__(self):
return self.title
class Skill(models.Model):
name = models.CharField(max_length=100, null=True, blank=True)
level = models.CharField(max_length=100, null=True, blank=True)
keywords = ArrayField(models.CharField(max_length=100), null=True, blank=True)
def __str__(self):
return self.name
class Language(models.Model):
language = models.CharField(max_length=100, null=True, blank=True)
fluency = models.CharField(max_length=100, null=True, blank=True)
def __str__(self):
return self.language
class Interest(models.Model):
name = models.CharField(max_length=100, null=True, blank=True)
keyword = ArrayField(models.CharField(max_length=100), null=True, blank=True)
def __str__(self):
return self.name
class Reference(models.Model):
name = models.CharField(max_length=100, null=True, blank=True)
reference = models.TextField(null=True, blank=True)
def __str__(self):
return self.name
class PersonalDetail(models.Model):
name = models.CharField(max_length=50, null=True, blank=True)
label = models.CharField(max_length=50, null=True, blank=True)
picture = models.ImageField(upload_to="", null=True, blank=True)
phone = PhoneNumberField(null=True, blank=True)
website = models.URLField(null=True, blank=True)
summary = models.TextField(null=True, blank=True)
def __str__(self):
return self.name
class Profile(models.Model):
profile = models.ForeignKey("resume.PersonalDetail", null=True, blank=True, on_delete=models.CASCADE)
social = models.ManyToManyField("resume.SocialProfile",
blank=True, related_name="social_profiles")
address = models.ForeignKey("resume.Location", null=True, blank=True, on_delete=models.CASCADE)
reference = models.ManyToManyField("resume.Reference", blank=True, related_name="profile_reference")
interest = models.ManyToManyField("resume.Interest", blank=True, related_name="interest")
language = models.ManyToManyField("resume.Language", blank=True, related_name="profile_language")
skill = models.ManyToManyField("resume.Skill", blank=True, related_name="profile_skill")
publication = models.ManyToManyField("resume.Publication", blank=True, related_name="profile_publication")
education = models.ManyToManyField("resume.Education", blank=True, related_name="profile_education")
work_history = models.ManyToManyField("resume.WorkHistory", blank=True, related_name="profile_work_history")
def __str__(self):
return self.profile.name

We simply created several model instances and using Profile model as our main table which connects to others either through a ForeignKey or ManyToManyField.

Go ahead and add the following in your “admin.py” inside your resume app to register your application in django admin interface.

from django.contrib import admin
from resume.models import (Reference,Interest,Language,
SocialProfile,PersonalDetail,Location,Education,Skill,Profile,
WorkHistory)
admin.site.register(SocialProfile)
admin.site.register(PersonalDetail)
admin.site.register(Location)
admin.site.register(Education)
admin.site.register(Skill)
admin.site.register(Reference)
admin.site.register(Interest)
admin.site.register(Language)
admin.site.register(Profile)
admin.site.register(WorkHistory)

Next add the code below in your views.py inside your resume application

import json
from django.http import HttpResponse
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework import status
from django.views import View
from resume.models import Profile
class ResumeView(View):
def get(self, request: Request) -> HttpResponse:
"""Retrieve all the data in the Profile db."""
profile = Profile.objects.prefetch_related().last()
if profile is not None:
json_data = json.dumps({
"profile": {"fullname": profile.profile.name,
"label": profile.profile.label,
"phone number": str(profile.profile.phone),
"website": profile.profile.website,
"summary": profile.profile.summary,},

"socials": [{"username": social.username,
"network": social.network,
"url": social.url}
for social in profile.social.all()],
"address": [{"city": profile.address.city,
"state": profile.address.state,
"country code": profile.address.country_code,
"country": profile.address.country,
"postal code": str(profile.address.postal_code),}
if profile.address is not None else {}],
"education": [{"institution": education.institution,
"course enrolled in": education.course_enrolled,
"study type": education.study_type,
"start date": str(education.start_date),
"end date": str(education.end_date),}
for education in profile.education.all()],
"skills": [{"name": skill.name,"level": skill.level,
"keywords": skill.keywords,}
for skill in profile.skill.all()],
"work history": [{"company": work.company,
"position": work.position,
"company_website": work.website,
"start date": str(work.start_date),
"end date": str(work.end_date),
"company_summary": work.company_summary,
"achievements": work.highlight,}
for work in profile.work_history.all()],
"publications": [{"title": publication.title,
"published on": publication.ppublished_on,
"date_published": publication.date_published,
"url": publication.website,}
for publication in profile.publication.all()],
})
return HttpResponse(json_data,status=200,
content_type="application/json",)
return HttpResponse("No profile found",status=200,
content_type="application/json",)

Navigate to your project “url.py”, the one in the same directory as your “settings.py” and add the code below

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

And in your resume “url.py”, add the following

from django.urls import path
from resume.views import ResumeView
urlpatterns = [
path("", ResumeView.as_view(), name="socialprofile")
]

Now let’s setup our ElephantSQL.
Why ElephantSQL though? I hosted this application on AWS EC2 and while developing it on my PC, I could get away with my application running on my local postgres setup, but when deployed on the cloud, the setup as expected stopped working.
Since I didn’t want to use Postgres from AWS(really because they didn’t have a free tier for postgres), I needed a platform, that offers database as a service. That was how I came across ElephantSQL. To read more about ElephantSQL, click here

To get started, go to https://www.elephantsql.com, register and login. After login, you will be redirected to your dashboard

elephantSQL dashboard

I already have a postgres instance running as you can see from the picture; your’s should be completly empty if this is your first time.
Click on “Create New Instance” and you will see the interface below.

Go ahead and fill in the name you want to call your instance, we will be using the Tiny Turtle plan(which is free as at the time of writing this article), add tags if you want and click on “Select Region”

select the data center you want and click on “Review” to review your instance details

click on ok and you will be redirected to your dashboard with your new instance created, click on the instance and the picture below is what you will see. We will be using the details on that page to set up our postgres on django settings

instance details

Navigate to your settings.py in your “ResumeJson” and add the following

DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
"NAME": "add the name of the user/default database on your elephant instance detail page",
"USER": "add the name of the user/default database on your elephant instance detail page",
"PASSWORD": "add the password from your elephant instance detail page",
"HOST": "add the server name from your elephance instance detail page",
"PORT": 5432,
}}

With all that done, go ahead and run the following

python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver

At this point your server should be running and if you navigate to 127.0.0.1:8000 on your browser, your application should be running there. Go to your admin interface 127.0.0.1:8000/admin and fill up all the tables.

If you navigate to your ElephantSQL instance dashboard, click on STATS tab, you will see that your data was successfully uploaded on the database.

elephantsql instance stats

Thanks for reading.

--

--

Anozie Baron Chibuikem

A backend engineer constantly building a shit ton of things with python and javascript and occasionally writes on technical topics.