Building a Simple Recipe App with Django

Welcome, aspiring web developers! Have you ever wanted to build your own website or web application but felt overwhelmed by all the complex terms and tools? You’re in luck! Today, we’re going to dive into Django, a powerful yet beginner-friendly web framework, to create a simple recipe application. By the end of this guide, you’ll have a basic web app up and running, and a solid foundation for your Django journey.

What is Django?

Django is a high-level Python web framework that encourages rapid development and clean, pragmatic design. Created by experienced developers, it takes care of much of the hassle of web development, so you can focus on writing your app without needing to reinvent the wheel. It’s often referred to as a “batteries-included” framework because it comes with many built-in features, like an admin panel, an Object-Relational Mapper (ORM), and a templating system.

  • Web Framework: A collection of modules, libraries, and tools that provide a structure for building web applications. Think of it as a toolkit that helps you build a house (your app) faster and more efficiently.
  • Python: A popular, easy-to-read programming language that Django is built with.
  • Object-Relational Mapper (ORM): A system that lets you interact with your database using Python code instead of writing raw SQL queries. This makes working with databases much simpler.
  • Templating System: A way to generate dynamic HTML content by mixing static HTML with Python variables and logic.

Our goal is to build a basic recipe app where you can list recipes, view their ingredients, and see their instructions. Simple, right? Let’s get started!

Prerequisites

Before we begin, please make sure you have the following installed:

  • Python 3: Django runs on Python. You can download it from the official Python website (python.org).
  • Basic understanding of the command line/terminal: We’ll be using commands to set up our project.

1. Setting Up Your Environment

It’s good practice to work within a virtual environment. This isolates your project’s dependencies from other Python projects you might have, preventing conflicts.

Create a Virtual Environment

Open your terminal or command prompt and navigate to where you want to store your project.

mkdir recipe_app
cd recipe_app
python -m venv venv
  • mkdir recipe_app: Creates a new folder named recipe_app.
  • cd recipe_app: Changes your current directory into this new folder.
  • python -m venv venv: Creates a virtual environment named venv inside your project folder.

Activate Your Virtual Environment

You’ll need to activate the virtual environment every time you start working on your project.

On macOS/Linux:

source venv/bin/activate

On Windows:

venv\Scripts\activate

You’ll notice (venv) appearing at the beginning of your command prompt, indicating that the virtual environment is active.

Install Django

Now that your virtual environment is active, install Django:

pip install django
  • pip: Python’s package installer. It’s like an app store for Python libraries.
  • install django: Tells pip to download and install the Django framework.

2. Creating Your First Django Project

A Django “project” is the entire web application, consisting of one or more “apps.”

django-admin startproject recipe_project .
  • django-admin: The command-line utility for Django.
  • startproject recipe_project: Creates a new Django project named recipe_project.
  • .: This tells Django to create the project files in the current directory, avoiding an extra nested folder.

Your folder structure should now look something like this:

recipe_app/
├── venv/
└── recipe_project/
    ├── manage.py
    └── recipe_project/
        ├── __init__.py
        ├── asgi.py
        ├── settings.py
        ├── urls.py
        └── wsgi.py
  • manage.py: A command-line utility that lets you interact with your Django project (e.g., run the server, create apps).
  • recipe_project/settings.py: Contains your project’s configuration (database settings, installed apps, etc.).
  • recipe_project/urls.py: Defines URL patterns for your entire project.

Run the Development Server

Let’s see if everything is working!

python manage.py runserver

You should see output similar to this:

Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
November 17, 2023 - 14:30:00
Django version 4.2.7, using settings 'recipe_project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Open your web browser and go to http://127.0.0.1:8000/. You should see a “The install worked successfully! Congratulations!” page. Press CTRL+C in your terminal to stop the server.

The message about “unapplied migrations” is normal. We’ll address that soon.

3. Creating a Django App

In Django, an “app” is a self-contained module that does one thing. Your project can have multiple apps (e.g., a “users” app, a “recipes” app, a “comments” app). Let’s create our recipes app.

python manage.py startapp recipes

Your folder structure now includes the recipes app:

recipe_app/
├── venv/
└── recipe_project/
    ├── manage.py
    ├── recipe_project/
    └── recipes/
        ├── migrations/
        ├── __init__.py
        ├── admin.py
        ├── apps.py
        ├── models.py
        ├── tests.py
        └── views.py

Register Your App

Django needs to know about the new recipes app. Open recipe_project/settings.py and add 'recipes' to the INSTALLED_APPS list.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'recipes', # Add your new app here
]

4. Defining Your Recipe Model

Models are how Django interacts with your database. Each model is a Python class that represents a table in your database, and each attribute of the class represents a column in that table.

Open recipes/models.py and define your Recipe model:

from django.db import models

class Recipe(models.Model):
    title = models.CharField(max_length=200)
    ingredients = models.TextField()
    instructions = models.TextField()
    cooking_time = models.IntegerField(help_text="in minutes", default=0)

    def __str__(self):
        return self.title
  • models.Model: All Django models inherit from this base class.
  • title = models.CharField(max_length=200): A field for the recipe’s title, limited to 200 characters.
  • ingredients = models.TextField(): A field for longer text, like a list of ingredients.
  • instructions = models.TextField(): Another text field for the cooking instructions.
  • cooking_time = models.IntegerField(...): A field for whole numbers, representing cooking time. help_text provides a hint in the admin interface, and default sets a default value.
  • def __str__(self):: This special method defines what to show when Django needs a string representation of a Recipe object (e.g., in the admin panel).

Make and Apply Migrations

Now that you’ve defined your model, you need to tell Django to create the corresponding table in your database.

python manage.py makemigrations recipes

This command tells Django to detect changes in your models (we just created Recipe) and create migration files. These files are like a set of instructions for modifying your database schema.

Next, apply these migrations:

python manage.py migrate

This command executes all pending migrations, including Django’s built-in ones (remember the “unapplied migrations” message?) and your new Recipe model. Django uses a default SQLite database, which is perfect for development.

5. The Django Admin Interface

Django comes with a built-in administrative interface that lets you manage your site’s content. It’s incredibly powerful and saves a lot of development time.

Create a Superuser

To access the admin interface, you need an administrator account.

python manage.py createsuperuser

Follow the prompts to create a username, email (optional), and password.

Register Your Model

Open recipes/admin.py and register your Recipe model so it appears in the admin interface:

from django.contrib import admin
from .models import Recipe

admin.site.register(Recipe)

Access the Admin Panel

Start your development server again:

python manage.py runserver

Go to http://127.0.0.1:8000/admin/ in your browser. Log in with the superuser credentials you just created.

You should now see “Recipes” under “Recipes” (the name of your app). Click on “Recipes” and then “Add recipe” to create your first recipe! Fill in the details and click “Save.”

Congratulations, you’ve just added data to your database through a custom Django model and the admin panel!

6. Creating Views and URLs

Now that we have data, let’s display it to users. This involves views and URLs.

  • Views: Python functions or classes that receive web requests and return web responses (like an HTML page).
  • URLs: Web addresses that users type into their browser. Django uses a urls.py file to map URLs to specific views.

Define a View

Open recipes/views.py and create a simple view to list all recipes:

from django.shortcuts import render
from .models import Recipe

def recipe_list(request):
    recipes = Recipe.objects.all() # Get all Recipe objects from the database
    context = {'recipes': recipes} # Package them into a dictionary
    return render(request, 'recipes/recipe_list.html', context)
  • from django.shortcuts import render: A helper function to load a template and pass it a context.
  • recipes = Recipe.objects.all(): This uses Django’s ORM to fetch all Recipe objects from the database.
  • context = {'recipes': recipes}: A dictionary that holds the data we want to send to our template.
  • return render(...): Renders the recipes/recipe_list.html template, passing the context data to it.

Define URLs for Your App

First, create a urls.py file inside your recipes app folder:

touch recipes/urls.py

Then, open recipes/urls.py and add the following:

from django.urls import path
from . import views

app_name = 'recipes' # This helps Django distinguish URLs if you have multiple apps

urlpatterns = [
    path('', views.recipe_list, name='recipe_list'),
]
  • from django.urls import path: Imports the path function to define URL patterns.
  • path('', views.recipe_list, name='recipe_list'): Maps the root URL of this app (the empty string '') to our recipe_list view. name='recipe_list' provides a convenient way to refer to this URL in templates and other parts of Django.

Include App URLs in the Project URLs

Finally, we need to tell the main recipe_project/urls.py file to include the URLs from our recipes app.

Open recipe_project/urls.py:

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('recipes/', include('recipes.urls')), # Include your app's URLs
]
  • path('recipes/', include('recipes.urls')): This means any URL starting with recipes/ will be handled by the urls.py file within our recipes app. So, http://127.0.0.1:8000/recipes/ will map to the recipe_list view.

7. Creating Basic Templates

Templates are HTML files with special Django syntax that allow you to display dynamic data from your views.

Create a Templates Folder

Inside your recipes app, create a templates folder, and inside that, another recipes folder. This is a common convention to prevent template name collisions if you have multiple apps.

recipes/
└── templates/
    └── recipes/
        └── recipe_list.html

Create Your Template File

Open recipes/templates/recipes/recipe_list.html and add the following HTML:

<!-- recipes/templates/recipes/recipe_list.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>All Our Recipes</title>
    <style>
        body { font-family: sans-serif; margin: 20px; }
        h1 { color: #333; }
        .recipe-card { border: 1px solid #eee; padding: 15px; margin-bottom: 10px; border-radius: 5px; }
        .recipe-card h2 { margin-top: 0; color: #007bff; }
        ul { list-style-type: none; padding: 0; }
        li { margin-bottom: 5px; }
    </style>
</head>
<body>
    <h1>Our Delicious Recipes</h1>

    {% if recipes %}
        {% for recipe in recipes %}
            <div class="recipe-card">
                <h2>{{ recipe.title }}</h2>
                <p><strong>Cooking Time:</strong> {{ recipe.cooking_time }} minutes</p>
                <h3>Ingredients:</h3>
                <ul>
                    {% for ingredient in recipe.ingredients.splitlines %}
                        <li>{{ ingredient }}</li>
                    {% endfor %}
                </ul>
                <h3>Instructions:</h3>
                <p>{{ recipe.instructions }}</p>
            </div>
        {% endfor %}
    {% else %}
        <p>No recipes found yet. Time to add some!</p>
    {% endif %}

</body>
</html>
  • {% if recipes %} / {% else %} / {% endif %}: Django template tags for conditional logic.
  • {% for recipe in recipes %} / {% endfor %}: Loops through the recipes list passed from the view.
  • {{ recipe.title }}: Double curly braces {{ }} are used to display the value of a variable.
  • {{ recipe.ingredients.splitlines }}: We’re assuming ingredients might be entered as new lines in the admin, so we use splitlines to turn them into a list for easier display.
  • A little inline CSS is added for basic styling, keeping it simple for now!

View Your Recipes!

Make sure your development server is running (python manage.py runserver).

Now, open your browser and go to http://127.0.0.1:8000/recipes/.

You should see a list of all the recipes you added through the Django admin!

Conclusion

Congratulations! You’ve successfully built a simple recipe application using Django. You’ve learned how to:

  • Set up a Django project and app.
  • Define database models.
  • Use Django’s powerful admin interface.
  • Create views to fetch data.
  • Map URLs to your views.
  • Display dynamic data using Django templates.

This is just the beginning! From here, you can expand your app by:

  • Adding more fields to your Recipe model (e.g., an image, a category).
  • Creating a detail page for each recipe.
  • Adding user authentication so users can submit their own recipes.
  • Styling your app with a proper CSS framework like Bootstrap.
  • Building forms for adding/editing recipes directly from the frontend.

Keep exploring, keep building, and don’t be afraid to experiment. Happy coding!


Comments

Leave a Reply