*The author selected the Mozilla Foundation to receive a donation as part of the Write for DOnations program.*

Introduction

As demand for full-stack development continues to grow, web frameworks are making development workflows less cumbersome and more efficient; Django is one of those frameworks. Django has been used in major websites such as Mozilla, Pinterest, and Instagram. Unlike Flask, which is a neutral micro-framework, the Django PyPI package includes everything you would need for full-stack development; no need to set up a database or control panel for development.

One common use-case for Django is to use it to display information from APIs (such as Instagram posts or GitHub repositories) in your own websites and web apps. While this is possible with other frameworks, Django's "batteries included" philosphy means there will be less hassle and fewer packages required to create the same result.

In this tutorial you will build a Django project that will display your cloud account's Droplet information using the the cloud provider v2 API. Specifically, you will be creating a website that will display a table of Droplets listing each of their IP addresses, IDs, hosting regions, and resources. Your website will use BulmaCSS to style the page so you can focus on development while also having something nice to look at in the end.

Once you complete this tutorial, you will have a Django project that can produce a webpage that looks like this:

Prerequisites

django illustration for: Prerequisites

Before you begin this guide you'll need the following:

  • A cloud account with at least one Droplet, and a personal access token. Make sure to record the token in a safe place; you'll need it later on in this tutorial.
  • A local virtual environment for Python for maintaining dependencies. In this tutorial we'll use the name <^>do_django_api<^> for our project directory and <^>env<^> for our virtual environment.
  • Familiarity with Django's template logic for rendering pages with API data.
  • Familiarity with Django's view logic for handling data recieved from the API and giving it to a template for rendering.

Step 1 — Making a Basic Django Project

From within the virtual environment <^>env<^>, install Django:

				
					
pip install Django

				
			

Now you can start a Django project and run some initial setup commands.

Use django-admin startproject <^><name><^> to create a subdirectory in the project folder named after your Django project, then switch to that directory.

				
					
django-admin startproject do_django_project

cd do_django_project

				
			

Once it's created, inside this subdirectory, you will find manage.py, which is the usual way to interact with Django and run your project. Use migrate to update Django's development database:

				
					
python3 manage.py migrate

				
			

You'll see output that looks like this as the database updates:

				
					
[secondary_label Output]

Operations to perform:

 Apply all migrations: admin, auth, contenttypes, sessions

Running migrations:

 Applying contenttypes.0001_initial... OK

 Applying auth.0001_initial... OK

 Applying admin.0001_initial... OK

 Applying admin.0002_logentry_remove_auto_add... OK

 Applying admin.0003_logentry_add_action_flag_choices... OK

 Applying contenttypes.0002_remove_content_type_name... OK

 Applying auth.0002_alter_permission_name_max_length... OK

 Applying auth.0003_alter_user_email_max_length... OK

 Applying auth.0004_alter_user_username_opts... OK

 Applying auth.0005_alter_user_last_login_null... OK

 Applying auth.0006_require_contenttypes_0002... OK

 Applying auth.0007_alter_validators_add_error_messages... OK

 Applying auth.0008_alter_user_username_max_length... OK

 Applying auth.0009_alter_user_last_name_max_length... OK

 Applying auth.0010_alter_group_name_max_length... OK

 Applying auth.0011_update_proxy_permissions... OK

 Applying sessions.0001_initial... OK

				
			

Next, use the runserver command to run the project so you can test it out:

				
					
python3 manage.py runserver

				
			

The output will look like this as the server starts:

				
					
[secondary_label Output]

Watching for file changes with StatReloader

Performing system checks...



System check identified no issues (0 silenced).

September 22, 2019 - 22:57:07

Django version 2.2.5, using settings 'do_django_project.settings'

Starting development server at http://127.0.0.1:8000/

Quit the server with CONTROL-C.

				
			

You now have a basic Django project and a development server running. To view your running development server, visit 127.0.0.1:8000 in a browser. It will display the Django startup page:

Next you'll create a Django app and configure your project to run a view from that app so you'll see something more interesting than the default page.

Step 2 — Making a Basic Django App

In this step, you'll create the skeleton of the app that will hold your Droplet results. You'll come back to this app later once you've set up the API call to populate it with data.

Make sure you're in the do_django_project directory, and create a Django app using the following command:

				
					
python3 manage.py startapp display_droplets

				
			

Now you need to add the new app to INSTALLED_APPS in the settings.py file, so Django will recognize it. settings.py is a Django configuration file that's located inside another subdirectory in the Django project and has the same name as the project folder (do_django_project). Django created both folders for you. Switch to the do_django_project directory:

				
					
cd do_django_project

				
			

Edit settings.py in the editor of your choice:

				
					
nano settings.py

				
			

Add your new app to the INSTALLED_APPS section of the file:

				
					
[label do_django_api/do_django_project/do_django_project/settings.py]

INSTALLED_APPS = [

 'django.contrib.admin',

 'django.contrib.auth',

 'django.contrib.contenttypes',

 'django.contrib.sessions',

 'django.contrib.messages',

 'django.contrib.staticfiles',

 # The new app

 &lt;^&gt;'display_droplets',&lt;^&gt;

]

				
			

Save and close the file when you're done.

GetDroplets View Function

Next you'll create a function, GetDroplets, inside the display_droplets app's views.py file. This function will render the template you'll use to display Droplet data, as context, from the API. context is a dictionary that is used to take data from Python code and send it to an HTML template so it can be displayed in a web page.

Switch to the display_droplets directory:

				
					
cd ..

cd display_droplets

				
			

Open views.py for editing:

				
					
nano views.py

				
			

Add the following code to the file:

				
					
[label do_django_api/do_django_project/display_droplets/views.py]

from django.views.generic import TemplateView



class GetDroplets(TemplateView):

 template_name = 'droplets.html'

 def get_context_data(self, *args, **kwargs):

 pass

				
			

Save and close the file.

Later you will populate this function and create the droplets.html file, but first let's configure urls.py to call this function when you visit the development server root directory (127.0.0.1:8000).

Switch back to the do_django_project directory:

				
					
cd ..

cd do_django_project

				
			

Open urls.py for editing:

				
					
nano urls.py

				
			

Add an import statement for GetDroplets, then add an additional path to urlpatterns that will point to the new view.

				
					
[label do_django_api/do_django_project/do_django_project/urls.py]

from django.contrib import admin

from django.urls import path

&lt;^&gt;from display_droplets.views import GetDroplets&lt;^&gt;



urlpatterns = [

 path('admin/', admin.site.urls),

 &lt;^&gt;path('', GetDroplets.as_view(template_name='droplets.html'), name='Droplet View'),&lt;^&gt;

]

				
			

If you want to make your own custom paths, the first parameter is the URL (such as example.com/admin), the second parameter is the function to call to produce the web page, and the third is just a name for the path.

Save and close the file.

Droplets Template

Next you'll be working with _templates_. Templates are HTML files that Django uses to create web pages. In this case, you'll use a template to construct an HTML page that displays the API data.

Switch back to the display_droplets directory:

				
					
cd ..

cd display_droplets

				
			

Inside this directory, create a template folder and switch to that directory:

				
					
mkdir templates

cd templates

				
			

Create droplets.html and open it for editing:

				
					
nano droplets.html

				
			

To avoid having to write any sort of CSS for this project, we'll use Bulma CSS because it's a free and lightweight CSS framework that allows you to create clean-looking web pages just by adding a few class attributes to the HTML.

Now let's create a template with a basic navigation bar. Add the following code to the droplets.html file.

				
					
[label do_django_api/do_django_project/display_droplets/templates/droplets.html]

&lt;!DOCTYPE html&gt;

&lt;html lang="en"&gt;

&lt;head&gt;

 &lt;meta charset="UTF-8"&gt;

 &lt;title&gt;cloud servers&lt;/title&gt;

 &lt;link crossorigin="anonymous"

 href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css"

 integrity="sha256-8B1OaG0zT7uYA572S2xOxWACq9NXYPQ+U5kHPV1bJN4="

 rel="stylesheet"/&gt;

 &lt;link rel="shortcut icon" type="image/png" href="https://www.progressiverobot.com/images/how-to-display-data-from-the-cloud-provider-api-with-django-section-1.png"/&gt;

&lt;/head&gt;

&lt;body&gt;

&lt;nav aria-label="main navigation" class="navbar is-light" role="navigation"&gt;

 &lt;div class="navbar-brand"&gt;

 &lt;div class="navbar-item"&gt;

 &lt;img atl="the cloud provider" src="https://www.progressiverobot.com/images/how-to-display-data-from-the-cloud-provider-api-with-django-section-1.png"

 style="margin-right: 0.5em;"&gt;Droplets

 &lt;/div&gt;

 &lt;/div&gt;

&lt;/nav&gt;

&lt;/body&gt;

&lt;/html&gt;

				
			

Save and close the file.

This code imports Bulma into boilerplate HTML and creates a nav bar displaying "Droplets."

Refresh your browser tab to view the changes you made to the template.

So far you haven't touched anything related to APIs; you've created a foundation for the project. Next you'll put this page to good use by making an API call and presenting the Droplet data.

Step 3 — Making The API Call

In this step, you'll set up an API call and send the Droplet data as context to the template to display in a table.

Getting Droplet Data

Navigate back to the display_droplets app directory:

				
					
cd ..

				
			

Install the requests library so you can talk to the API:

				
					
pip install requests

				
			

The requests library enables your code to request data from APIs and add headers (additional data sent along with our request).

Next, you'll create a services.py file, which is where you'll make the API call. This function will use requests to talk to https://developer.mozilla.org/en-US/docs/Web/HTTP and append each Droplet in the JSON file returned to a list.

Open services.py for editing:

				
					
nano services.py

				
			

Add the following code to the file:

				
					
[label do_django_api/do_django_project/display_droplets/services.py]

import os

import requests



def get_droplets():

 url = 'https://developer.mozilla.org/en-US/docs/Web/HTTP'

 r = requests.get(url, headers={'Authorization':'Bearer %s' % '&lt;^&gt;access_token&lt;^&gt;'})

 droplets = r.json()

 droplet_list = []

 for i in range(len(droplets['droplets'])):

 droplet_list.append(droplets['droplets'][i])

 return droplet_list

				
			

Inside the get_droplets function, two things occur: a request is made and data is parsed. url contains the URL requesting Droplet data from the cloud provider API. r stores the requested data.

requests takes two parameters in this case: url and headers. If you want data from a different API, you'd replace the url value with the appropriate URL. headers sends the cloud provider your access token, so they know you're allowed to make the request and for what account the request is being made.

droplets contains the information from the r variable, but now it has been converted from JSON, the format the API sends information in, into a dictionary which is easy to use in a for loop.

The next three lines create an array, droplet_list[]. Then a for loop iterates over the information in droplets, and adds each item to the list. All of the information taken from the API and stored in droplets can be found in the cloud provider's Developer Docs.

Note: Don't forget to replace access_token with your access token. Also, keep it safe and never publish that token online.

Save and close the file.

Protecting Your Access Token

You should always hide your access token, but if someone ever wanted to run your project, you should have an easy way for them to add their own access token without having to edit Python code. DotENV is the solution as variables are kept in a .env file that can be conveniently edited.

Navigate back to the do_django_project directory:

				
					
cd ..

				
			

To start working with environment variables, install python-dotenv:

				
					
pip install python-dotenv

				
			

Once it's installed, you need to configure Django to handle environment variables, so you can reference them in code. To do that, you need to add a few lines of code to manage.py and wsgi.py.

Open manage.py for editing:

				
					
nano manage.py

				
			

Add the following code:

				
					
[label do_django_api/do_django_project/manage.py]



"""Django's command-line utility for administrative tasks."""

import os

import sys

&lt;^&gt;import dotenv&lt;^&gt;



def main():

 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'do_django_project.settings')

 try:

 from django.core.management import execute_from_command_line

 except ImportError as exc:

 raise ImportError(

 "Couldn't import Django. Are you sure it's installed and "

 "available on your PYTHONPATH environment variable? Did you "

 "forget to activate a virtual environment?"

 ) from exc

 execute_from_command_line(sys.argv)



if __name__ == '__main__':

 main()



&lt;^&gt;dotenv.load_dotenv(&lt;^&gt;

 &lt;^&gt;os.path.join(os.path.dirname(__file__), '.env')&lt;^&gt;

&lt;^&gt;)&lt;^&gt;

				
			

Adding this in manage.py means that when you issue commands to Django in development it will handle environment variables from your .env file.

Save and close the file.

If you ever need to handle environment variables in your production projects, you can do that from the wsgi.py file. Change to the do_django_project directory:

				
					
cd do_django_project

				
			

And open wsgi.py for editing:

				
					
nano wsgi.py

				
			

Add the following code to wsgi.py:

				
					
[label do_django_api/do_django_project/do_django_project/wsgi.py]



import os

&lt;^&gt;import dotenv&lt;^&gt;



from django.core.wsgi import get_wsgi_application



os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'do_django_project.settings')



&lt;^&gt;dotenv.load_dotenv(&lt;^&gt;

 &lt;^&gt;os.path.join(os.path.dirname(os.path.dirname(__file__)), '.env')&lt;^&gt;

&lt;^&gt;)&lt;^&gt;



application = get_wsgi_application()

				
			

This code snippet has an additional os.path.dirname() because wsgi.py needs to look two directories back to find the .env file. This snippet is not the same as the one used for manage.py.

Save and close the file.

Now you can use an environment variable in services.py instead of your access token. Switch back to the display_droplets directory:

				
					
cd ..

cd display_droplets

				
			

Open services.py for editing:

				
					
nano services.py

				
			

Now replace your access token with an environment variable:

				
					
[label do_django_api/display_droplets/services.py]

import os

import requests



def get_droplets():

 url = "https://developer.mozilla.org/en-US/docs/Web/HTTP"

 r = requests.get(url, headers={'Authorization':'Bearer %s' % &lt;^&gt;os.getenv('DO_ACCESS_TOKEN')&lt;^&gt;})

 droplets = r.json()

 droplet_list = []

 for i in range(len(droplets['droplets'])):

 droplet_list.append(droplets['droplets'][i])

 return droplet_list

				
			

Save and close the file.

The next step is to create a .env file. Switch back to the do_django_project directory:

				
					
cd ..

				
			

Create a .env file and pen the file for editing:

				
					
nano .env

				
			

In .env, add your token as the variable DO_ACCESS_TOKEN:

				
					
[label do_django_api/do_django_project/.env]

DO_ACCESS_TOKEN=&lt;^&gt;access_token&lt;^&gt;

				
			

Save and close the file.

Note: Add .env to your .gitignore file so it is never included in your commits.

The API connection is now set up and configured, and you've protected your access token as well. It's time to present the information you retrieved to the user.

Step 4 — Handling Droplet Data in Views and Templates

Now that you can make API calls, you need to send the Droplet data to the template for rendering. Let's return to the stub of the function, GetDroplets you created earlier in views.py. In the function you'll send droplet_list as context to the droplets.html template.

Switch to the display_droplets directory:

				
					
cd display_droplets

				
			

Open views.py for editing:

				
					
nano views.py

				
			

Add the following code to views.py:

				
					
[label do_django_api/do_django_project/display_droplets/views.py]

from django.shortcuts import render

from django.views.generic import TemplateView

&lt;^&gt;from .services import get_droplets&lt;^&gt;



class GetDroplets(TemplateView):

 template_name = 'droplets.html'

 def get_context_data(self, *args, **kwargs):

 &lt;^&gt;context = {&lt;^&gt;

 &lt;^&gt;'droplets' : get_droplets(),&lt;^&gt;

 &lt;^&gt;}&lt;^&gt;

 &lt;^&gt;return context&lt;^&gt;

				
			

Information sent to the droplets.html template is handled via the context dictionary. This is why droplets acts as a key and the array returned from get_droplets() acts as a value.

Save and close the file.

Presenting the Data in the Template

Inside the droplets.html template you'll create a table and populate it with the droplet data.

Switch to the templates directory:

				
					
cd templates

				
			

Open droplets.html for editing:

				
					
nano droplets.html

				
			

Add the following code after the nav element in droplets.html:

				
					
[label do_django_api/do_django_project/display_droplets/templates/droplets.html]

&lt;table class="table is-fullwidth is-striped is-bordered"&gt;

 &lt;thead&gt;

 &lt;tr&gt;

 &lt;th&gt;Name&lt;/th&gt;

 &lt;th&gt;IPv4 Address(es)&lt;/th&gt;

 &lt;th&gt;Id&lt;/th&gt;

 &lt;th&gt;Region&lt;/th&gt;

 &lt;th&gt;Memory&lt;/th&gt;

 &lt;th&gt;CPUs&lt;/th&gt;

 &lt;th&gt;Disk Size&lt;/th&gt;

 &lt;/tr&gt;

 &lt;/thead&gt;

 &lt;tbody&gt;

 {% for droplet in droplets %}

 &lt;tr&gt;

 &lt;th&gt;{{ droplet.name }}&lt;/th&gt;

 {% for ip in droplet.networks.v4 %}

 &lt;td&gt;{{ ip.ip_address }}&lt;/td&gt;

 {% endfor %}

 &lt;td&gt;{{ droplet.id }}&lt;/td&gt;

 &lt;td&gt;{{ droplet.region.name }}&lt;/td&gt;

 &lt;td&gt;{{ droplet.memory }}&lt;/td&gt;

 &lt;td&gt;{{ droplet.vcpus }}&lt;/td&gt;

 &lt;td&gt;{{ droplet.disk }}&lt;/td&gt;

 &lt;/tr&gt;

 {% endfor %}

 &lt;/tbody&gt;

&lt;/table&gt;

				
			

{% for droplet in droplets %} ... {% endfor %} is a loop that iterates through the array of Droplets retrieved from views.py. Each Droplet is inserted in a table row. The various {{ droplet.<attribute> }} lines retrieve that attribute for each Droplet in the loop, and inserts it in a table cell.

Save and close the file.

Refresh your browser and you will see a list of Droplets.

You can now handle the cloud provider API inside your Django projects. You've taken the data retrieved from the API and plugged it into the template you created earlier, to display the information in a readable and flexible manner.

Conclusion

In this article you built a Django project that can display Droplet information from the cloud provider API with Bulma CSS styling. You've learned three important skills by following this tutorial:

  • How to handle API requests in Python using the requests and json modules.
  • How to display API data in a Django project using view and template logic.
  • How to safely handle your API tokens using dotenv in Django.

Now that you've gotten an introduction to handling APIs in Django, you can create a project of your own using either another feature from the cloud provider API or another API altogether. You can also check out other Django tutorials or a similar tutorial with the React framework.