DEV Community

Cover image for Building a Currency Converter in Django: A Step-by-Step Guide
Rohitash Singh
Rohitash Singh

Posted on • Updated on

Building a Currency Converter in Django: A Step-by-Step Guide

In today's interconnected world, handling currency conversion is a common requirement for many web applications. In this tutorial, we will walk through the process of building a simple currency converter using Django, a powerful Python web framework. By the end of this guide, you'll have a functional currency converter that users can interact with.

Prerequisites
Before we start, ensure you have the following installed on your system:

  • Python
  • Django

You can install Django using the following command:

pip install python
pip install django
Enter fullscreen mode Exit fullscreen mode

Setting Up the Django Project

Let's begin by creating a new Django project. Open your terminal and run the following commands:

django-admin startproject currency_converter
cd currency_converter
Enter fullscreen mode Exit fullscreen mode

Next, create a new Django app within the project:

python manage.py startapp converter
Enter fullscreen mode Exit fullscreen mode

Building the Views
Define the views in the views.py file of the converter app:

from django.shortcuts import render
import requests

def get_currency_data():
    """ Fetch currency data from the API """
    url = "https://open.er-api.com/v6/latest/USD"
    try:
        response = requests.get(url)
        response.raise_for_status()
        currency_data = response.json()
        return currency_data
    except requests.exceptions.RequestException as e:
        print(f"Error fetching currency data: {e}")
        return None
    except ValueError as e:
        print(f"Error decoding JSON response: {e}")
        return None

def index(request):
    currency_to = "USD"
    result = None

    if request.method == "POST":
        try:
            amount = float(request.POST.get('amount'))
            currency_from = request.POST.get("currency_from")
            currency_to = request.POST.get("currency_to")
        except (ValueError, TypeError):
            result = "Invalid input"
        else:
            url = f"https://open.er-api.com/v6/latest/{currency_from}"
            try:
                response_data = requests.get(url).json()
                if "result" in response_data and response_data["result"] == "success":
                    rates = response_data.get("rates", {})
                    ex_target = rates.get(currency_to)
                    if ex_target is not None:
                        result = "{:.2f}".format(ex_target * amount)
                    else:
                        result = "Currency not found"
                else:
                    result = "Error fetching exchange rates"
            except requests.exceptions.RequestException as e:
                result = f"API request failed: {e}"

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

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

Enter fullscreen mode Exit fullscreen mode

Creating Templates
Create two HTML templates: base.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="icon" href="images/favicon.png" type="image/png">
    <title>{% block title %} {% endblock title %} - Converter </title>

    <link rel="stylesheet" href="static/css/font-awesome.min.css"> 
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css"
        integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

    <link rel="stylesheet" href="static/css/style_1.css">
</head>

<body>

    <header class="header_area">
        <div class="main_menu">
            <nav class="navbar navbar-expand-lg navbar-light">
                <div class="container">
                    <a class="navbar-brand logo_h" href="/">
                        ExchangeX
                        <!-- <img src="" height="70" alt> -->
                    </a>
                    <button class="navbar-toggler" type="button" data-toggle="collapse"
                        data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>

                    <div class="collapse navbar-collapse offset" id="navbarSupportedContent">
                        <ul class="nav navbar-nav menu_nav justify-content-end">
                            <li class="nav-item"><a class="nav-link" href="https://rohitashsingh.vercel.app"
                                    target="_blank">About</a></li>
                        </ul>
                    </div>
                </div>
            </nav>
        </div>
    </header>


    {% block body %}

    {% endblock body %}


    <footer class="footer_area">
        <div class="container">
            <div class="row justify-content-center">
                <div class="col-lg-12">
                    <div class="footer_top flex-column">
                        <div class="footer_logo">
                            <a href="/">
                                <h1>ExchangeX</h1>
                            </a>
                            <h4>Follow Us</h4>
                        </div>
                        <div class="footer_social">
                            <a href="https://facebook.com/timrock89"><i class="fa fa-facebook"></i></a>
                            <a href="https://twitter.com/rohitashsingh89"><i class="fa fa-twitter"></i></a>
                            <a href="https://github.com/rohitashsingh89"><i class="fa fa-github"></i></a>
                        </div>
                    </div>
                </div>
            </div>
            <div class="row footer_bottom justify-content-center">
                <p class="col-lg-8 col-sm-12 footer-text">

                    Copyright ©
                    <script>document.write(new Date().getFullYear());</script> All rights reserved!! <br> Designed with
                    <i class="fa fa-heart-o text-danger" aria-hidden="true"></i> by <a
                        href="https://rohitashsingh.vercel.app" target="_blank">Rohitash Singh</a>
                </p>
            </div>
        </div>
    </footer>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"
        integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r"
        crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.min.js"
        integrity="sha384-BBtl+eGJRgqQAUMxJ7pMwbEyER4l1g+O15P+16Ep7Q9Q+zqX6gSbd85u4mG4QzX+"
        crossorigin="anonymous"></script>

    <link rel="stylesheet" href="static/js/script.js">


</body>

</html>

Enter fullscreen mode Exit fullscreen mode

index.html

{% extends 'base.html' %}
{% load static %}
{% block title %} Home {% endblock title %}
{% block body %}

<section style="padding-top: 20vh;">
  <div class="container text-center">
    <h1 class="text-dark mb-5">
      Foreign Currency Exchange Rate Converter

    </h1>
  </div>
</section>

<div class="container">
  <div class="row mx-auto">
    <div class="col-lg-12">
      <div>
        <form method="post" class="p-2" style="box-shadow: 0 2px 5px 0 rgb(0 0 0 / 16%), 0 2px 10px 0 rgb(0 0 0 / 12%);"
          action="{% url 'index' %}">
          {% csrf_token %}
          <div class="header text-center mb-5">
            We Use Mid-Market Exchange Rates
          </div>
          <div class="d-flex justify-content-between align-items-center px-5">
            <div class="my-auto">
              <label>Amount</label> <br>
              <input type="text" class="form-control" name="amount" id="amount" placeholder="Amount">
            </div>

            <div class="left-column">
              <div>
                <label>From</label>
                <div>
                  <select id="currency_from" name="currency_from">
                    {% for currency_code, currency_rate in currency_data.rates.items %}
                    <option value="{{ currency_code }}">{{ currency_code }}</option>
                    {% endfor %}
                  </select>

                </div>
              </div>

            </div>

            <a href="javascript:void(0);" role="button" class="swap-btn" aria-label="swap-button" onclick="swapValues()"
              title="swap" style="width: 74px;">⇄</a>

            <div class="right-column max-height: 150px;">
              <div>
                <label>To</label>
                <div style=" overflow-y: auto;">
                  <select id="currency_from" name="currency_to" class="selectpicker" data-live-search="true"
                    data-size="5">
                    {% for currency_code, _ in currency_data.rates.items %}
                    <option value="{{ currency_code }}">{{ currency_code }}</option>
                    {% endfor %}
                  </select>
                </div>
              </div>
            </div>
          </div>

          <div class="footer text-center my-3 mt-5">
            <input type="submit" value="Convert" class="btn btn-primary">
          </div>

          <h2 class="text-center my-3">{{ result }} {{ currency_to }}</h2>
        </form>

        <div class="error" id="formErrorBlock" style="display: none">
          <h3 id="formErrorMsg"></h3>
        </div>

        <br>
      </div>
    </div>
  </div>
</div>


{% endblock body %}

Enter fullscreen mode Exit fullscreen mode

Building Urls


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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('converter.urls'))
]

Enter fullscreen mode Exit fullscreen mode

please write css according to your requirements or design pattern.

This is how we learn how to create currency converter in python.
Feel free to make it super advance. You can store exchange rate in database and many more.
Thank you for reading my Blog.

Happy Coding!.

Top comments (0)