How to Create a Food Website (using the Spoonacular API) [Python & Flask]

food website detailed recipe page

Nutrition is an essential aspect of human life but many people have problems with it.

Some don’t have enough time and passion for eating healthy food, while others like to cook the same old dishes.

Today we will solve this issue, improve our diet, and learn how to create a beautiful web application for recipe search using APIs.

How to Create a Food Website with an API

  1. Choose the right Recipe API
  2. Add a Search Functionality with the Recipe API
  3. Create a Search Results Page
  4. Create a Detailed Recipe Page

If you’re looking to start a food blog, this link may be helpful. (Don’t forget to SEO your food blog, like building backlinks and promotion.)

Spoonacular’s Recipe, Food, & Nutrition API

For our purposes, we’ll be using the Spoonacular API as the targeted data source.

It is a comprehensive database for food information and data. 

You can find and share enormous amounts of recipes in real-life.

This API includes over 365,000 recipes, which includes over 80,000 ingredients, making it one of the best recipe APIs that includes full access to recipes and cooking instructions.

Also, the API allows for searching the recipes and cooking procedures via natural language. For example, you can search for something like “vegan desserts”, and you should receive some comprehensive search results.

Spoonacular has powerful calculation features for calories, pricing, and many other aspects. A potential user can even see a visualization of different meals of different cuisines.

Finally, there is a space for custom diets.

You can submit your particular diet, or follow the rules of some specific diet template.

This is only the tip of the iceberg – there are even associated chatbots and an ingredients autocompleting system!

How to use and get an API key to the Spoonacular API

RapidAPI Free API Key

In order to use the Spoonacular API, we will be using the RapidAPI platform.

Simply, sign up for a free RapidAPI user account and subscribe to the API.  (hint: there’s a Basic Plan that allows you to do 500 free requests/day).

recipe api pricing

We’ll be coding in Python for this project, and we will create a Flask application with a bright demonstration of the nutrition API power. So be sure to have Python 3.7 on your machine.

Recipe API Overview

spoonacular food recipe nutrition api endpoints

 Here are some of the top API endpoints:

The medial side responds to the headers and parameters within the chosen endpoint.

Here, you can check your unique RapidAPI id and host of the tested product.

It is a very informative way to meet a user with a request functionality.

Each input field has a description; you can change and test different combinations of them.

If you would like to see the results of the previously mentioned tests, look to the right side, you can find code snippets for all supported programming languages

Now let’s review a practical example.

How to Build a Food App or Website using the Spoonacular API

“What’s in your fridge” website

Once in awhile, we’ll peek into our fridge and make some strange food combinations.

Let’s create an app that helps us find recipes given the ingredients we have available.

1. Create a Search Page

First, let’s create a starting point for our users with a search page. If the user chooses not to type anything, the system still will back a few random propositions.

After that, the user can choose and open a detailed view of a single recipe. Each page should include dynamic information and use multiple API endpoints. The full list of them is as follows:

  • GET random joke – just a funny way to say hello;
  • GET recipes by ingredients’ enumeration – the basic type of recipe search. Ingredients are typed with comma-separator;
  • GET random recipes – in case of user’s interest in something new; 
  • GET recipe information by ID – detailed text info with a recipe image;
  • VISUALIZE recipe ingredients by ID – default HTML-widget from Spoonacular for the ingredients demonstration;
  • VISUALIZE recipe equipment by ID – one more widget, but for the equipment.

As mentioned before, we will make a web application using Python, so we will need a framework. Luckily, Python has a swift and very lightweight solution called Flask – a microframework, which is also quite an active programming tool. Don’t forget to install it into your Python environment.

pip install flask

The next required library – requests. It is one of the possible solutions for HTTP requests handling. 

pip install requests

Now you can create a folder for a web-app and .py file. Let’s use Bootstrap for a prettified HTML layout – an open-sourced library for many CSS templates.

Next, we will create a templates subfolder with all the layout snippets. Each of them will be executed after the backside data processing. You need to have a method-handler per each unique data action. This method should render a template with a dynamic response creating.

Next, let’s use Jinja2 – a method of connecting Python code with HTML templates. It’s a syntax language for Python commands using mark-up. Okay, let’s now code something!

First, let’s create a base.html file that will be a basic template for all of the next steps.

<!doctype html>
<html lang="en">
  <head>
  <!-- Required meta tags -->
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">

  <!-- Optional JavaScript -->
  <!-- jQuery first, then Popper.js, then Bootstrap JS -->
  <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>

  <title>{% block title %} Base page {% endblock %}</title>
  </head>
  <body>
  {% block body %}
    	Body block
  {% endblock %}
  </body>
</html>

Here we include all the required style files and create blocks for the dynamic data.

Now we can try to work with the .py file.

Paste the following lines in it:

from flask import Flask, render_template, request

import requests
app = Flask(__name__)

url = "https://spoonacular-recipe-food-nutrition-v1.p.rapidapi.com/"

headers = {
  'x-rapidapi-host': "spoonacular-recipe-food-nutrition-v1.p.rapidapi.com",
  'x-rapidapi-key': "<YOUR_RAPID_API_KEY>",
  }

random_joke = "food/jokes/random"
find = "recipes/findByIngredients"
randomFind = "recipes/random"

@app.route('/')
def search_page():
  joke_response = str(requests.request("GET", url + random_joke, headers=headers).json()['text'])
  return render_template('search.html', joke=joke_response)

if __name__ == '__main__':
  app.run()

Now we’ll create some global variables for the endpoints.

Let’s also route the home page with the search.

After receiving the joke, we pass it to the template.

Now create and modify search.html in the following way:

{% extends 'base.html' %}
{% block title %} Recipes searcher {% endblock %}
{% block body %}

<center>
  <h2 style="padding-top: 3%;">
    	It's time for cooking! What do you have in the fridge? <br>
    	<small class="text-muted"> Let's warm up with a joke: {{ joke }} </small>
  </h2>
  <br><br>
  <form action="/recipes">
    	<div class="input-group mb-3" style="max-width: 50%;">
        	<input type="text" class="form-control" placeholder="Apple, flour, sugar" aria-label="Ingridients" aria-describedby="button-addon2" name="ingridients">
        	<div class="input-group-append">
            	<button class="btn btn-outline-secondary" type="submit" id="button-addon2">Search</button>
        	</div>       	 
    	</div>
  </form>
</center>
{% endblock %}

Pretty simple layout creation. But let’s try to execute our project by running the .py file.

food website search functionality

2. Create a Recipe Search Results Page

Now let’s display the search results.

Let’s display them in a list, so we will need one more method-handler + template.

We can start with the first one.

Paste the following code under the search_page method within the .py file.

@app.route('/recipes')
def get_recipes():
  if (str(request.args['ingridients']).strip() != ""):
    	# If there is a list of ingridients -> list
    	querystring = {"number":"5","ranking":"1","ignorePantry":"false","ingredients":request.args['ingridients']}
    	response = requests.request("GET", url + find, headers=headers, params=querystring).json()
    	return render_template('recipes.html', recipes=response)
  else:
    	# Random recipes
    	querystring = {"number":"5"}
    	response = requests.request("GET", url + randomFind, headers=headers, params=querystring).json()
    	print(response)
    	return render_template('recipes.html', recipes=response['recipes'])

Here we will request two different endpoints depending on the search results.

But don’t forget about the templates.

Create a recipes.html file and paste the following lines:

{% extends 'base.html' %}
{% block title %} Recipes searcher {% endblock %}
{% block body %}
<h2 style="text-align: center"> <a href="/" style="text-decoration: none; color:red"> Recipes for you: </a></h2>
<div style="margin-left:35%;">
  <ul class="list-unstyled">
    	{% for recipe in recipes %}
        	<li class="media">
            	<img src="{{recipe['image']}}" class="align-self-center mr-3" alt="..." width="15%" height="15%">
            	<div class="media-body">
                	<h5 class="mt-0 mb-1"><a href="/recipe?id={{ recipe['id'] }}">{{ recipe['title'] }}</a></h5>
                	{% if 'likes' not in recipe%}
                    	How many minutes for preparation? {{recipe['preparationMinutes']}} <br>
                    	How many minutes for cooking? {{recipe['cookingMinutes']}}  <br>
                    	How many likes has this recipe? {{recipe['aggregateLikes']}}  <br>
                	{% else %}
                    	How many your ingridients? {{recipe['usedIngredientCount']}} <br>
                    	How many missed ingridients? {{recipe['missedIngredientCount']}}  <br>
                    	How many likes has this recipe? {{recipe['likes']}}  <br>
                	{% endif %}
            	</div>
        	</li> <br>
    	{% endfor %}
  </ul>
</div >
{% endblock %}

Again, there is a clear separation of two different ways of generating recipes. 

Now let’s test it. Let’s try searching for something:

food website search results page

Here are the results for “pork, lemon, honey”.

The user can compare the original recipe and the pointed products.

But how will our app work without any search?

food website results page

When no search is performed, five random dishes are displayed, including the amount of time required for preparing and cooking.

3. Create detailed Recipe Pages

Now, let’s get a detailed display of the recipes. Let’s start with a usual method in the .py file.

@app.route('/recipe')
def get_recipe():
  recipe_id = request.args['id']
  recipe_info_endpoint = "recipes/{0}/information".format(recipe_id)
  ingedientsWidget = "recipes/{0}/ingredientWidget".format(recipe_id)
  equipmentWidget = "recipes/{0}/equipmentWidget".format(recipe_id)

  recipe_info = requests.request("GET", url + recipe_info_endpoint, headers=headers).json()
    
  recipe_headers = {
    	'x-rapidapi-host': "spoonacular-recipe-food-nutrition-v1.p.rapidapi.com",
    	'x-rapidapi-key': "<YOUR_RAPID_API_KEY>",
    	'accept': "text/html"
  }
  querystring = {"defaultCss":"true", "showBacklink":"false"}

  recipe_info['inregdientsWidget'] = requests.request("GET", url + ingedientsWidget, headers=recipe_headers, params=querystring).text
  recipe_info['equipmentWidget'] = requests.request("GET", url + equipmentWidget, headers=recipe_headers, params=querystring).text
    
  return render_template('recipe.html', recipe=recipe_info)

Here you’ll see some interesting new lines of code.

First, let’s execute three requests, instead of one.

Second, we will create sub-headers to satisfy the accept header requirements for the content type.

Finally, we will include a default CSS for the widget integration.

Create a recipe.html template and paste the following snippet:

{% extends 'base.html' %}
{% block title %} {{recipe['title']}} {% endblock %}
{% block body %}

<div style="max-width: 70%; margin: auto; padding-top:3%">
  <div class="media">
    	<img src="{{recipe['image']}}" class="mr-3" alt="..." width="20%" height="20%">
    	<div class="media-body">
      	<h5 class="mt-0">{{recipe['title']}}</h5>
      	{{recipe['instructions']}}
    	</div>
  </div><br>
  {{recipe['inregdientsWidget'] | safe }}<br>
  {{recipe['equipmentWidget'] | safe}}
</div>
{% endblock %}

Voila! The app is completed.

Of course, it isn’t ideal yet, but even now it has many interesting aspects to surf.

The most important thing: “| safe” keyword.

This code indicates HTML markup, so all tags and scripts will be executed. Rerun your project and visit some recipe pages.

food website detailed recipe page

Conclusion

Today we have introduced the Spoonacular API.

It is a powerful and multi-functional solution for food nutrition.

We created a visible and robust web application.

The basis of this app was made via RapidAPI endpoints.

Our project can propose fresh recipes depending on the contents of your fridge. 

 

 

5
/
5
(
1

vote

)

The post How to Create a Food Website (using the Spoonacular API) [Python & Flask] appeared first on The Last Call – RapidAPI Blog.

Source: RapidAPI