Learn Django by Building a Calculator App

Django is a high-level Python web framework that enables rapid development of secure and maintainable websites. Its popularity has grown immensely in recent years – according to the Stack Overflow Developer Survey 2021, Django is now the 4th most popular web framework overall, used by 43.4% of professional developers. If you‘re a Python developer looking to branch into web development, or a web developer wanting to learn a powerful new framework, Django is an excellent choice.

In this in-depth tutorial, we‘ll learn the core concepts of Django by building a practical project from scratch – a web-based calculator application. We‘ll cover everything from setting up a new Django project to deploying the finished app, with detailed explanations and code samples at every step. By the end, you‘ll have a strong foundation in Django development and the skills to build your own robust web applications.

Project Setup

Before we start coding, we need to create a new Django project and app for our calculator. If you don‘t already have Django installed, you can install it from PyPI using pip:

pip install django

With Django installed, open a terminal and run the following command to start a new project:

django-admin startproject calculator

This creates a new directory called calculator with the basic Django project structure:

calculator/
    calculator/
        __init__.py
        asgi.py
        settings.py
        urls.py
        wsgi.py
    manage.py

Next, we‘ll create an app within this project to hold our calculator code:

cd calculator
python manage.py startapp calculator_app

We then need to add the new calculator_app to our project‘s INSTALLED_APPS setting in calculator/settings.py:

INSTALLED_APPS = [
    ‘calculator_app.apps.CalculatorAppConfig‘,
    ‘django.contrib.admin‘,
    ‘django.contrib.auth‘,
    ‘django.contrib.contenttypes‘,
    ‘django.contrib.sessions‘,
    ‘django.contrib.messages‘,
    ‘django.contrib.staticfiles‘,
]

With the app registered, we‘re ready to start building the calculator interface.

Designing the Calculator Interface

We‘ll define our calculator‘s user interface using Django‘s template system and HTML forms. In the calculator_app directory, create a new directory called templates and add a file named calculator.html with the following contents:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Calculator</title>
</head>
<body>

    <form method="post">
        {% csrf_token %}
        <input type="text" name="expression" required>
        <button type="submit">Calculate</button>
    </form>
    <h2>Result: {{ result }}</h2>
</body>
</html>

This template defines a simple form with a text input for entering a mathematical expression and a submit button to calculate the result. The {% csrf_token %} tag includes Django‘s Cross-Site Request Forgery protection, which is a critical security feature.

To display this template, we need to define a corresponding view in calculator_app/views.py:

from django.shortcuts import render

def calculator(request):
    return render(request, ‘calculator.html‘)

And then map a URL to this view in calculator_app/urls.py:

from django.urls import path
from . import views

urlpatterns = [
    path(‘‘, views.calculator, name=‘calculator‘),
]

Finally, update the project-level calculator/urls.py to include the app‘s URLs:

from django.urls import include, path

urlpatterns = [
    path(‘‘, include(‘calculator_app.urls‘)),
]

Now if you run the Django development server with python manage.py runserver and visit http://localhost:8000, you‘ll see the calculator form.

Parsing Expressions and Calculating Results

To make the calculator functional, we need to modify the calculator view to handle form submissions, parse the entered mathematical expression, and return the calculated result.

Parsing mathematical expressions is a complex task, as it requires handling operator precedence and nested parentheses. Rather than attempting to write an expression parser from scratch, we can leverage the powerful eval() function built into Python. eval() evaluates a string as a Python expression and returns the result.

Here‘s an updated version of the calculator view that uses eval() to calculate the result:

def calculator(request):
    if request.method == ‘POST‘:
        expression = request.POST[‘expression‘]
        try:
            result = eval(expression)
        except (SyntaxError, ZeroDivisionError, NameError, TypeError, ValueError):
            result = ‘Invalid input‘
        context = {‘result‘: result}
    else:
        context = {}
    return render(request, ‘calculator.html‘, context)

This view checks if the request method is POST, indicating a form submission. If so, it extracts the expression from the form data and passes it to eval() inside a try/except block. If the expression is valid, eval() will return the calculated result. If there‘s an error in the expression (like invalid syntax, dividing by zero, or referencing undefined variables), the result will be set to ‘Invalid input‘.

The result is then passed to the template context so it can be rendered in the HTML.

With this updated view, the calculator can now handle basic arithmetic expressions entered into the form. Try entering an expression like 2 + 3 * 4 and you‘ll see the correct result (14) displayed.

Enhancing the Calculator

While our calculator is now functional, there are many ways we could enhance it. Let‘s implement a few additional features to make it more useful and user-friendly.

Handling Errors

Right now, if a user enters an invalid expression, the calculator simply displays "Invalid input". We can improve this by showing more specific error messages. Modify the except block in the calculator view like this:

except SyntaxError:
    result = ‘Syntax error‘
except ZeroDivisionError:
    result = ‘Cannot divide by zero‘
except (NameError, TypeError, ValueError):
    result = ‘Invalid input‘

Now the calculator will display a more helpful message depending on the type of error.

Clearing the Form

It would be useful to have a way to clear the form and start a new calculation. We can add a "Clear" button to the template:

<button type="button" onclick="document.querySelector(‘input[name=expression]‘).value=‘‘">Clear</button>

Clicking this button will clear the value of the expression input, effectively resetting the form.

Keyboard Support

To make the calculator more efficient to use, we can add support for keyboard entry. With a few lines of JavaScript, we can allow users to type their expression and submit the form by pressing Enter:

<script>
    document.querySelector(‘input[name=expression]‘).addEventListener(‘keyup‘, function(e) {
        if (e.key === ‘Enter‘) {
            document.querySelector(‘button[type=submit]‘).click();
        }
    });
</script>

This script listens for the Enter key to be pressed while the expression input is focused, and programmatically clicks the submit button.

Styling with Bootstrap

So far, our calculator‘s interface is very plain. We can greatly improve its appearance by integrating the popular Bootstrap CSS framework. First, include the Bootstrap CSS file in the <head> of the template:

<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">

Then, we can use Bootstrap classes to style the form elements:

<div class="container my-5">
    <h1 class="text-center mb-4">Calculator</h1>
    <div class="row justify-content-center">
        <div class="col-sm-6">
            <form method="post">
                {% csrf_token %}
                <div class="mb-3">
                    <input type="text" name="expression" class="form-control form-control-lg" required>
                </div>
                <div class="d-grid gap-2">
                    <button type="submit" class="btn btn-primary btn-lg">Calculate</button>
                    <button type="button" class="btn btn-secondary btn-lg" onclick="document.querySelector(‘input[name=expression]‘).value=‘‘">Clear</button>
                </div>
            </form>
            <h2 class="text-center mt-4">Result: {{ result }}</h2>
        </div>
    </div>
</div>

This adds much more visual appeal to the calculator interface with just a few Bootstrap classes.

Testing the Calculator

An important part of building any application is testing it to ensure it behaves as expected. Django provides a built-in testing framework that makes it easy to write and run tests for your apps.

Let‘s create a simple test case for our calculator view. In the calculator_app directory, create a new file called test_views.py with the following code:

from django.test import TestCase, Client
from django.urls import reverse

class CalculatorTests(TestCase):
    def setUp(self):
        self.client = Client()
        self.calculator_url = reverse(‘calculator‘)

    def test_valid_expression(self):
        response = self.client.post(self.calculator_url, {‘expression‘: ‘2+3*4‘})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, ‘14‘)

    def test_invalid_expression(self):
        response = self.client.post(self.calculator_url, {‘expression‘: ‘2+‘})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, ‘Syntax error‘)

    def test_division_by_zero(self):
        response = self.client.post(self.calculator_url, {‘expression‘: ‘1/0‘})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, ‘Cannot divide by zero‘)

This test case class defines three test methods:

  1. test_valid_expression submits a valid arithmetic expression and checks that the response contains the correct result.
  2. test_invalid_expression submits an expression with invalid syntax and verifies that the appropriate error message is returned.
  3. test_division_by_zero tries to divide by zero and confirms that the cannot divide by zero message appears in the response.

To run these tests, use the python manage.py test command:

Creating test database for alias ‘default‘...
System check identified no issues (0 silenced).
...
----------------------------------------------------------------------
Ran 3 tests in 0.041s

OK
Destroying test database for alias ‘default‘...

Automated tests like these help ensure the reliability and correctness of your application, and make it easier to catch bugs as you continue to enhance and modify the code.

Deploying the Calculator App

Once you‘ve developed your Django app, the final step is to deploy it to a web server so that others can access it online. There are many options for deploying Django apps, from traditional VPS (Virtual Private Server) hosting to fully-managed platforms.

One popular and beginner-friendly option is PythonAnywhere, which provides a free tier for hosting Python web apps. Here‘s a high-level overview of the steps to deploy our calculator app on PythonAnywhere:

  1. Sign up for a free PythonAnywhere account at https://www.pythonanywhere.com/registration/register/beginner/

  2. Open a Bash console from the PythonAnywhere dashboard.

  3. Clone your calculator app‘s source code from your Git repository (you‘ll need to push your code to GitHub or a similar service first).

  4. Create a new virtual environment and install Django and any other dependencies:

    mkvirtualenv --python=/usr/bin/python3.9 calculator-env
    pip install django
  5. Create a new web app from the PythonAnywhere "Web" tab, selecting "Manual configuration" and your Django project‘s virtual environment.

  6. Update the ALLOWED_HOSTS setting in your project‘s settings.py file to include your PythonAnywhere subdomain:

    ALLOWED_HOSTS = [‘yourusername.pythonanywhere.com‘]
  7. Set up your static files by creating a new static files mapping in the "Static files" section of the web app configuration page.

  8. Reload your web app, and visit https://yourusername.pythonanywhere.com to see your deployed calculator!

Full detailed instructions for deploying Django apps to PythonAnywhere are available in their help documentation: https://help.pythonanywhere.com/pages/DeployExistingDjangoProject

Other popular platforms for deploying Django apps include Heroku, DigitalOcean, AWS, and Microsoft Azure. Each has its own setup process and considerations, but the general steps are similar: upload your code, install dependencies, configure settings, and launch the web app.

Conclusion

In this tutorial, we‘ve walked through the process of building a functional calculator app with the Django web framework. Along the way, we‘ve learned about Django‘s key concepts and architecture, including:

  • Creating a new Django project and apps
  • Defining views to handle HTTP requests and return responses
  • Designing user interfaces with Django‘s template language
  • Processing form submissions and user input
  • Integrating styling with CSS frameworks like Bootstrap
  • Writing automated tests for Django views
  • Deploying Django apps to production servers

Building a project like this calculator app is an excellent way to gain practical experience with Django and web development in general. It requires using a variety of web technologies (HTML, CSS, JavaScript, Python) and putting into practice concepts like MVC architecture, server-side processing, and web security.

But this is just the beginning! There are many more possibilities for enhancing the calculator, like adding a history feature, allowing multiple expressions to be entered, or even turning it into a full scientific calculator. You could also explore other areas of Django, like working with databases and forms, user authentication, or building REST APIs.

Django is a powerful and versatile web framework that‘s used by companies like Instagram, Mozilla, NASA, and more. It prioritizes clean, pragmatic design and rapid development, making it an excellent choice for all sorts of web applications. By learning Django, you‘re not only gaining a valuable tool for building your own projects, but also an in-demand skill for web development jobs.

As you continue on your Django learning journey, remember that the best way to learn is by doing. Build more projects, experiment with new features and packages, and don‘t be afraid to make mistakes. With practice and persistence, you‘ll soon be a Django pro!

Similar Posts