Last updated: 21 August 2026

Nowadays, Django currency API integration has become common for modern applications. You can observe it especially in applications dealing with international financial data or e-commerce. Unlike a simple Python script, developers focus on performance, scalability, and architecture maintenance when implementing this integration.

In this tutorial, we explain Django currency API integration within an app. We will cover caching strategies, views, background updates using Celery, and API endpoints with Django REST framework. Let’s begin.

Prerequisites & Setup

  • Python 3.x and Django installed in a virtual environment.
  • Requests library: pip install requests
  • Django REST Framework: pip install djangorestframework
  • CurrencyFreaks API Key: Sign up to get your free API key. Still choosing a provider? Compare the 10 best currency exchange APIs first.
  • Celery: pip install celery
  • Redis client: pip install redis

currency converter api integration with Django to get historical exchange rates or historical data

Fetching Rates in a Django View

Model-view-template is essential when working with the Django currency API. We do not follow hardcoding approaches. Instead, we focus on creating a structured view. This view fetches the data and passes it to the frontend.

views.py

from django.shortcuts import render

def exchange_dashboard(request):
    
    data = get_cached_rates() # defined in "Caching Strategy" section below 
    
    context = {
        'rates': data.get('rates'),
        'base': data.get('base'),
        'date': data.get('date')
    }
    return render(request, 'exchange/dashboard.html', context)

Your template (exchange/dashboard.html) allows you to access and navigate a rates dictionary while dynamically displaying currency values with Django template tags.

Note: In the next section, we'll define the get_cached_rates() function.

urls.py

from django.urls import path
from .views import exchange_dashboard

urlpatterns = [
    path('dashboard/', exchange_dashboard, name='exchange-dashboard'),
]

Exchange Rate API Django — Caching Strategy

Django workflow for an exchange rate API should not include hitting external APIs on every single page load; as rates typically update every hour, Django's built-in cache framework can reduce latency and save on API credits. The CurrencyFreaks free plan includes 1,000 API calls per month, so caching allows thousands of users to share a single hourly API request.

from django.core.cache import cache
from django.conf import settings
import requests


def get_cached_rates():
    rates = cache.get('latest_currency_rates')

    if not rates:
        api_key = settings.CURRENCYFREAKS_API_KEY
        try:
            response = requests.get(
                f"https://api.currencyfreaks.com/v2.0/rates/latest?apikey={api_key}",
                timeout=5
            )
            rates = response.json()
            cache.set('latest_currency_rates', rates, 3600)
        except requests.exceptions.RequestException:
            return {}

    return rates

Utilizing the cache.get()/cache.set() pattern ensures your application remains responsive even during high traffic volumes.

Building a Currency Conversion Endpoint with Django REST Framework

If you are developing an independent frontend or mobile app, a Django REST Framework currency API endpoint can help expose conversion logic as a professional JSON API.

serializers.py

from rest_framework import serializers

class ConversionSerializer(serializers.Serializer):
    from_currency = serializers.CharField(max_length=3)
    to_currency = serializers.CharField(max_length=3)
    amount = serializers.FloatField()

views.py (DRF)

from rest_framework.views import APIView
from rest_framework.response import Response

class ConvertCurrency(APIView):
    def get(self, request):
        serializer = ConversionSerializer(data=request.query_params)

        if not serializer.is_valid():
            return Response(serializer.errors, status=400)

        rates = get_cached_rates()

        from_currency = serializer.validated_data['from_currency']
        to_currency = serializer.validated_data['to_currency']
        amount = serializer.validated_data['amount']

        rates_data = rates.get('rates', {})

        from_rate = rates_data.get(from_currency)
        to_rate = rates_data.get(to_currency)

        if from_rate is None or to_rate is None:
            return Response(
                {'error': 'Invalid or unsupported currency code'},
                status=400
            )

        from_rate = float(from_rate)
        to_rate = float(to_rate)

        # Note: Formula assumes USD is the base currency from the API provider.
        converted_amount = (amount / from_rate) * to_rate

        return Response({
            'from': from_currency,
            'to': to_currency,
            'amount': amount,
            'converted_amount': round(converted_amount, 2)
        })

This approach ensures your currency conversion Django logic remains organized and usable across applications.

urls.py (DRF Endpoint)

from django.urls import path
from .views import ConvertCurrency

urlpatterns = [
    path('api/convert/', ConvertCurrency.as_view(), name='currency-convert'),
]

Example API Request

GET /api/convert/?from_currency=USD&to_currency=EUR&amount=100

JSON Response:

{
    "from": "USD",
    "to": "EUR",
    "amount": 100.0,
    "converted_amount": 91.23
}

Scheduled Rate Updates with Celery

For an optimal Django Celery exchange rates implementation, it is ideal to fetch rates in the background so as to maintain "warm" cache conditions while never having to wait on 3rd-party API responses. This way, users never need to wait in their search for rates from third parties.

tasks.py

from celery import shared_task
import requests
from django.core.cache import cache
from django.conf import settings

@shared_task
def update_rates_task():
    api_key = settings.CURRENCYFREAKS_API_KEY
    response = requests.get(f"https://api.currencyfreaks.com/v2.0/rates/latest?apikey={api_key}")
    if response.status_code == 200:
        cache.set('latest_currency_rates', response.json(), 3600)

Celery Beat Configuration (settings.py)

CELERY_BEAT_SCHEDULE = {
   'update-rates-every-hour': {
       'task': 'exchange.tasks.update_rates_task',
       'schedule': 3600.0,
   },
}

Celery Beat configuration is placed in settings.py so Django can register scheduled tasks correctly in production setups.

Add your API key in settings.py using environment variables:

# settings.py
import os

CURRENCYFREAKS_API_KEY = os.getenv("CURRENCYFREAKS_API_KEY")

This avoids exposing sensitive credentials in source control.
Error Handling & Production Readiness

In real-life scenarios, APIs may fail, so your Django app must gracefully handle currency conversion requests when they do so.

import requests
import logging
from rest_framework.views import APIView
from rest_framework.response import Response
from django.core.cache import cache
from .serializers import ConversionSerializer

logger = logging.getLogger(__name__)


class SafeConvertCurrency(APIView):
    def get(self, request):
        serializer = ConversionSerializer(data=request.query_params)

        if not serializer.is_valid():
            return Response(serializer.errors, status=400)

        try:
            rates = get_cached_rates()
        except requests.exceptions.RequestException as e:
            logger.error(f"Currency API failed: {e}")
            rates = cache.get('latest_currency_rates')

            if not rates:
                return Response(
                    {'error': 'Exchange rate service unavailable'},
                    status=503
                )

        from_currency = serializer.validated_data['from_currency']
        to_currency = serializer.validated_data['to_currency']
        amount = serializer.validated_data['amount']

        rates_data = rates.get('rates', {})

        from_rate = rates_data.get(from_currency)
        to_rate = rates_data.get(to_currency)

        if from_rate is None or to_rate is None:
            return Response(
                {'error': 'Invalid or unsupported currency code'},
                status=400
            )

        from_rate = float(from_rate)
        to_rate = float(to_rate)

        # Note: Formula assumes USD is the base currency from the API provider.
        converted_amount = (amount / from_rate) * to_rate

        return Response({
            'from': from_currency,
            'to': to_currency,
            'amount': amount,
            'converted_amount': round(converted_amount, 2)
        })

By combining DRF as the interface, the Django Cache for performance, and Celery for background processing, you create a robust system capable of handling exchange rates with professionalism.

Conclusion

By aligning currency integration with Django's architecture, including views, caching, API endpoints, and background workers, you can avoid unnecessary API calls while increasing performance.

Django Cache reduces latency, Django REST Framework provides clean APIs, and Celery keeps exchange rates updated without blocking user requests, all making for an approach that is production-ready and scalable for applications handling real-time financial data.

FAQs

How Should I Handle Currency Conversion in Django Templates?

For best results, currency conversion should be handled using an exchange rate view context with either custom template filters or multiplication; for optimal UI, use a Django REST Framework endpoint that handles calculations via JavaScript instead. This ensures updated pricing doesn't necessitate full page reloads to display accurately.

Where Is the Best Place to Store Exchange Rates in Django?

For high-performance applications, temporary storage (e.g., 1 hour) should be handled using Redis or Memcached Cache; for historical reports or audit trails, however, rates should be stored in your primary database using an ExchangeRate model that updates regularly via Celery tasks.

Why Should I Use Celery for Currency Updates Instead of Updating on Page Load?

Updating on page load forces users to wait for third-party API responses, adding significant latency and risking a 504 Gateway Timeout if an API goes down. Django Celery exchange rates management allows you to fetch data in the background so your users always see a "warm" cache with no wait time for updates.

How Do I Handle API Rate Limits in a Django Project?

One effective strategy to remain within CurrencyFreaks plan limits is by employing a cache.get()/cache.set() cycle, checking cache first before only hitting the API when data has expired. This allows for thousands of users to be served using one API call per hour!

Is It Better to Use a Decimal or Float Field for Currency in Django Models?

Always use DecimalField when storing currency values in your models, since floats can lead to rounding errors that cause lost pennies. Also, ensure your currency conversion Django logic converts API responses into Decimals before performing calculations to maintain financial accuracy.

Sign Up for free at CurrencyFreaks and get your business's most accurate exchange rates.