Pantry Database Part 2: Django Front End

Awhile ago, I wrote a post on an idea for a pantry app that I wanted to develop.  It’s been a little while since I’ve visited this project and thought it was well overdue for me to make some progress on it.

In the first part, I designed and built a SQLite database backend for the app.  Now that I’m more experienced with databases, I am beginning to get a much better feel for when to use MySQL and when to use SQLite (or even something else).  Early on during this project, I wanted to use a SQLite database (I knew that this is the database used on phones and I was wanting to get a better handle on using SQLite).

A major feature of this app is that I want it to sync somehow between my phone and my boyfriend’s phone (and maybe even more devices).  By design, SQLite can’t be accessed by multiple users at the same time and you can’t easily access it on a remote server.  It could be possible to do this app with SQLite as initially planned, but it would go against what SQLite is built to do.  Because of that, I redid the database in MySQL.

I think the front end will be a lot more difficult for me to accomplish than the database back end.  I decided to do the front end in Django, since it is Python based and that is my strongest language.  I wrote a seven part Django tutorial recently.  The end goal of that was to have enough of an understanding of Django to build my pantry front end.  In this post, we’ll try to start getting that up and running!

Basic Design

I have never designed a web app on my own.  However, I have designed GUIs and simple webpages and I believe some of the design steps will be similar.  The first thing we want to do is get an idea of what we want the app to do and what we want it to look like.  In the first part of this series, we discussed the doing so now it is time to figure out how it will look.

There are two major functions of this web app: a list of pantry items and a list of recipes.  To start, I want to just get the recipes portion up and running (I believe this will be the more difficult of the two and I’m feeling up for a challenge).

I want the app to function first and then I will worry about the aesthetics later.  Therefore, on the front page, I’d like the app to look something like this:

  • Cookbook
    • Top Recipes
      • Top Recipe 1
      • Top Recipe 2
    • Most Recent Recipes
      • Most Recent Recipe 1
      • Most Recent Recipe 2

Each of these items should be links.  The top Cookbook link will go to a page that has all of the recipes and ways to sort them.  The Top Recipes link will go to a similar page, but with it automatically sorted by rating (or just our favorite recipes).  Finally, the Most Recent Recipes will be the same, but ordered by date.  The recipe links will go to the page that shows the actual recipe.

Create The App

The first step will be to create the app.  I already have a folder called pantrio.  I’ll navigate to that directory and type the command:

python startapp cookbook

This creates a folder called cookbook within my pantrio directory.  Inside this directory are the following folders and files:


Make sure that this creates the file.  Older versions of Django might not create the file automatically and it is needed.  If it doesn’t add the file, delete the cookbook directory, update Django through pip, and try again.

Create The View

Think of the file as essentially a group of classes which will help define the look of specific elements on different pages.  For example, this is where we will define that we want our recipes to be listed alphabetically.  Open the cookbook/ file and add the following to it:

from django.shortcuts import render
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.views import generic
from django.utils import timezone
from django.core.urlresolvers import reverse

from .models import Recipe, Ingredient

# Create your views here.
class IndexView(generic.ListView):
 template_name = 'cookbook/index.html'
 context_object_name = 'latest_recipe_list'
 # order most recent
 # def get_queryset(self):
 # return Recipe.objects.filter(date_created__lte ='-date_created')[:5]
 # order alphabetically
 def get_queryset(self):
 return Recipe.objects.order_by('-recipe_title').reverse()[:5]
class DetailView(generic.DetailView):
 model = Recipe
 template_name = 'cookbook/recipe_view.html'

class ResultsView(generic.DetailView):
 model = Recipe
 template_name = 'cookbook/results.html'

The IndexView class is for the index page (the main or front page), the DetailView page is for recipes, and the ResultsView is a temporary view that might be used in the future.

Within each class, we define the template that we will be using (we will create this actual file later) as well as any specifics for how the elements should be organized.

Next, we need to link these views to URLs.  Create a file within the cookbook directory called and put the following in it:

from django.conf.urls import url

from . import views

app_name = 'cookbook'
urlpatterns = [
 url(r'^$', views.IndexView.as_view(), name='index'),
 url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='recipe_view'),
 url(r'^(?P<pk>[0-9]+)/results/$', views.ResultsView.as_view(), name='results'),

This defines the URL patterns for the app and links them to our views that we just defined.  Now, we need to link these URLs to the project.  Open the file pantrio/ and edit it to look like this:

urlpatterns = [
    url(r'^polls/', include('polls.urls',namespace="polls")),
    url(r'^cookbook/', include('cookbook.urls'),

This tells the project that we are wanting to include our new Cookbook urls and views.

Update the Database

Any time we add new views or models, we need to update the database.  To do that, navigate to the folder that contains the file and type the command

python migrate

Create The Model

The models define what information will be in the elements on a specific page.  For the recipes, we have three major items: the recipes themselves (name, date created, total prep time, number of servings, etc), ingredients (including the amounts), and the steps.  Each of these items gets its own class in the models file:

from __future__ import unicode_literals
import datetime
from django.db import models

# Create your models here.
class Recipe(models.Model):
 recipe_title = models.CharField(max_length = 200)
 date_created = models.DateField('date created',

 def __str__(self):
 return self.recipe_title

class Ingredient(models.Model):
 recipe = models.ForeignKey(Recipe, on_delete = models.CASCADE)
 ingredient_name = models.CharField(max_length = 200)
 amount = models.CharField(max_length = 50)
 def __str__(self):
 return self.ingredient_name
class Step(models.Model):
 recipe = models.ForeignKey(Recipe, on_delete = models.CASCADE)
 step_text = models.CharField(max_length = 255)
 def __str__(self):
 return self.step_text

Though the syntax is quite different, this is very similar to defining tables in a database.  In fact, Django will create a database based on the information in these tables!  We need to be careful that our data types (such as CharField, DateField, etc) are correct and large enough.

Activate The Model

Since we made changes to the model, we need to “migrate” it.  This essentially means telling Django to update and/or create any new tables into the database.  Navigate to the project’s settings file (for me, this is pantrio/ and add the following to the INSTALLED_APPS list:


Finally, navigate to the file and run the command:

python makemigrations cookbook

You should receive an output that looks something like this:

Migrations for 'cookbook':
    - Create model Ingredient
    - Create model Recipe
    - Add field recipe to ingredient

Make the App Modifable in the Admin

Next, we need to make the Cookbook app modifable in the admin tool (this is off by default).  Navigate to the cookbook/ file and add the following:

from django.contrib import admin

# Register your models here.
from .models import Recipe, Ingredient, Step

class IngredientInLine(admin.TabularInline):
    model = Ingredient
    extra = 10

class StepInLine(admin.TabularInline):
    model = Step
    extra = 10
class RecipeAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields':['recipe_title']}),
        ('Date information', {'fields':['date_created'], 'classes':['collapse']}),
    inlines = [IngredientInLine, StepInLine]
    list_display = ('recipe_title', 'date_created')
    list_filter = ['date_created']
    search_fields = ['recipe_title'], RecipeAdmin)

This tells the admin tool what we want to be able to edit (Ingredient and Step) and in general how we want it to look.  Check to make sure it works by going to:

Create .html Templates

Finally, we need to create the templates.  This could be done at any time, and perhaps maybe should be done first so that you can test after each step.  However, without knowing what views and models you will use, it might be difficult to create the templates.

First, create a series of folders like this within the cookbook directory: templates/cookbook/

Next, create your .html templates.  For me, this is index.html, recipe_view.html, and results.html.

My index.html file contains this:

{% load staticfiles %}

<link rel="stylesheet" type="text/css" href="{% static 'cookbook/style.css' %}" />
{% for recipe in latest_recipe_list %}
    <li><a href="{% url 'cookbook:recipe_view' %}">{{ recipe.recipe_title }}</a></li>
{% endfor %}

This puts “Cookbook” large on the top of the page, then lists each recipe title in bullet points.  Each of these is a link.  They are alphabetized because our view orders them alphabetically.

Next, the recipe_view.html file is the template for each actual recipe.  That file contains:

{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static 'cookbook/style.css' %}" />

<h1>{{ recipe.recipe_title }}</h1>
{% for ingredient in recipe.ingredient_set.all %}
    <li> {{ingredient.amount}} &nbsp - &nbsp {{ ingredient.ingredient_name }} </li>
{% endfor %}
    {% for ingredient in recipe.ingredient_set.all %}
    {% endfor %}
{% for step in recipe.step_set.all %}
    <li> {{step.step_text}}</li>
{% endfor %}

<a href = "{% url 'cookbook:index' %}">Back</a>

Check to make sure it works:

Add A Recipe With The Admin Tool

Finally, lets add a recipe and check it out!  Go to the admin tool ( and click on Recipes under Cookbook:


On the upper right portion of the page, click “Add Recipe + “.  You’ll be taken to a page that looks like this:


Fill in the information for the recipe and click save.  Next, go to the app (  I’ve added three recipes, so my cookbook page looks like this:


A recipe page looks like this:


That’s it!  I’m pretty excited to have this app up and running.  Before starting this, I still didn’t have a good feel for Django, even though I went through the 7 part tutorial.  This project helped me understand Django a lot more and I’m excited to be able to use this new tool.  Next, I’d like to add the following capabilities (this list is not in any order):

  • Add more recipe information (serving size, number of calories, prep time, total time, etc)
  • Add search capabilities (by recipe name, ingredient(s), number of calories, etc)
  • Add filtering capabilities to search/browse
  • Add pantry inventory capabilities
  • Make the app look and feel a little more professional

Have questions or suggestions?  Please feel free to comment below or contact me.

Leave a Reply

Your email address will not be published. Required fields are marked *