How to build a currency converter in Django

How to build a currency converter in Django

This article will explain how to build a currency converter app. This app can convert from to all world currencies.

First of all, let's see what we'll build:

Final project

Now let's get started.

Technologies

In this tutorial, we'll use these requirements:

  • Django==4.0.4
  • requests==2.27.1
  • open.er-api.com API

Project structure

After installing and creating the Django project, this is what the project structure looks like:

├── currency_converter
│   ├── core
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── __init__.py
│   │   ├── migrations
│   │   ├── models.py
│   │   ├── __pycache__
│   │   ├── tests.py
│   │   └── views.py
│   ├── currency_converter
│   │   ├── asgi.py
│   │   ├── __init__.py
│   │   ├── __pycache__
│   │   ├── settings.py
│   │   ├── urls.py
│   │   └── wsgi.py
│   ├── db.sqlite3
│   ├── manage.py
│   └── TEMPLATES
│       └── index.html

 Build a currency converter

To build a currency converter, we first need countries' currency data. Therefore we will download currencies.json from Github currencies data and put it in the core directory.

currencies.json:

[
  {"cc":"AED","symbol":"\u062f.\u0625;","name":"UAE dirham"},
  {"cc":"AFN","symbol":"Afs","name":"Afghan afghani"},
  {"cc":"ALL","symbol":"L","name":"Albanian lek"},
  {"cc":"AMD","symbol":"AMD","name":"Armenian dram"},
  {"cc":"ANG","symbol":"NA\u0192","name":"Netherlands Antillean gulden"},
  {"cc":"AOA","symbol":"Kz","name":"Angolan kwanza"},
  {"cc":"ARS","symbol":"$","name":"Argentine peso"},
  {"cc":"AUD","symbol":"$","name":"Australian dollar"},
  {"cc":"AWG","symbol":"\u0192","name":"Aruban florin"},
  {"cc":"AZN","symbol":"AZN","name":"Azerbaijani manat"},
..
..
.

In view.py, we need to write a function that converts currencies.json to a dictionary.

from django.shortcuts import render
import requests
import json
import os


def currency_data():
    """ All countries' currency data """
    module_dir = os.path.dirname(__file__)  # get current directory
    file_path = os.path.join(module_dir, 'currencies.json')
    with open(file_path, "r") as f:
        currency_data = json.loads(f.read())
    return currency_data

Next, create our converter page view and return the currency_data() function in it.

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

Next, in the index.html, we'll write the converter form.

<html>
   <head>
      <title>Currency converter</title>
      <style>
         *, *:before, *:after {
         box-sizing: border-box;
         }
         html, body {
         width: 100%;
         height: 100%;
         margin: 0;
         padding: 0;
         }
         body {
         display: flex;
         justify-content: center;
         align-items: center;
         font: normal 10px 'Open Sans', sans-serif;
         margin: 0;
         -webkit-font-smoothing: antialiased;
         color: #4c4c4c;
         background: #3f44a5;
         }
         .clear {
         clear: both;
         }
         h1 {
         text-align: center;
         font-size: 22px;
         color: white;
         }
         .select-wrapper {
         position: relative;
         width: 350px;
         }
         .select-wrapper::after {
         color: black;
         content: '▾';
         margin-right: 10px;
         pointer-events: none;
         position: absolute;
         right: 10px;
         top: 7px;
         font-size: 20px;
         }
         .select {
         -moz-appearance: none;
         -webkit-appearance: none;
         background: white;
         border: none;
         border-radius: 0;
         cursor: pointer;
         padding: 12px;
         width: 100%;
         font-size: 18px;
         }
         .select:focus {
         color: black;
         }
         .select::-ms-expand {
         display: none;
         }
         input{ width: 100%; height: 50px;}
         h2 {color: #fff; text-align: center; font-size: 35px;}
      </style>
   </head>
   <body>
      <div class="container">
         <h1>Currency Converter</h1>
         <form method="post" action="{% url 'index' %}">
         {% csrf_token %}
         <!-- Amount input -->
         <div class="select-text">
            <input  name="amount" type="text">
         </div>
         <br>
         
         <div class="select-wrapper">
            <!-- From options -->
            <select name="currency_from" class="select">
               {% for c in currency_data %}
               <option value="{{c.cc}}">{{c.name}}</option>
               {% endfor %}
            </select>
         </div>
         <br>
         <div class="select-wrapper">
            <!-- To options -->
            <select name="currency_to" class="select">
               {% for c in currency_data %}
               <option value="{{c.cc}}">{{c.name}}</option>
               {% endfor %}
            </select>
         </div>
         <br>
         <div class="select-submit">
            <input type="submit" value="Convert">
         </div>
         <!-- Converter result -->
         <h2>{{ result }} {{ currency_to }}</h2>
      </div>
   </body>
</html>

Next, in urls.py, we need to add a path for our index view.

from django.contrib import admin
from django.urls import path
# Views
from core.views import index

urlpatterns = [
    path('admin/', admin.site.urls),
    # Index
    path('', index, name='index')
]

Now, let's see the result on the browser.

open http://127.0.0.1:8000/

index page
form select

Now, it's time to write our form handling in view.py inside the index view.

def index(request):
    
    if request.method == "POST":

        # Get data from the html form
        amount = float(request.POST.get('amount'))
        currency_from = request.POST.get("currency_from")
        currency_to = request.POST.get("currency_to")

        # Get currency exchange rates
        url = f"https://open.er-api.com/v6/latest/{currency_from}"
        d = requests.get(url).json()

        # Converter
        if d["result"] == "success":
            
            # Get currency exchange of the target
            ex_target =  d["rates"][currency_to]

            # Mltiply by the amount
            result = ex_target * amount

            # Set 2 decimal places
            result = "{:.2f}".format(result)

            context = {
            "result":result, 
            "currency_to":currency_to, 
            "currency_data":currency_data()
            }

            return render(request, "index.html", context)


    return render(request, "index.html", {"currency_data":currency_data()})

To understand The logic to calculate the converter, let's say we want to convert 100 U.S dollars to Euro:

  1. Send a request to https://open.er-api.com/v6/latest/USD
  2. Get the exchange rate of the U.S dollar to Euro
  3. Multiply exchange rate of Euro by 100

Here is the final project:

Final project

You can also download the project via GitHub by clicking the following link:
Project on Github

Conclusion

In this tutorial, we've learned how to build the currency converter. To make the app stable, you need to add more form validations.

If you want to see how to build a translator app, check the link below:
Django Translator | Building a Translator app Step by Step

Happy Coding ♥