Introduction: Enhancing Our Cooking API

Welcome back! In the last lesson, you learned how to make your cooking assistant more accessible by generating audio instructions using the gTTS library. Now, we are going to make your API even more useful and interactive by adding two new features: the ability to list all available ingredients and to let users submit reviews for recipes.

These features are important for any smart cooking app. Listing ingredients helps users see what’s available or filter recipes, while reviews allow users to share feedback and help others find the best recipes. By the end of this lesson, you will know how to build and test these endpoints in Flask.

Quick Recall: Flask Endpoints Refresher

Before we dive in, let’s quickly remind ourselves how Flask endpoints work. In Flask, an endpoint is a function that runs when a user visits a certain URL. You define endpoints using the @app.route decorator, and you can specify which HTTP methods (like GET or POST) the endpoint should accept.

For example, here’s a simple GET endpoint:

  • The @app.route('/hello', methods=['GET']) line tells Flask to run the say_hello function when someone visits /hello using the GET method.
  • The function returns a JSON response.

In this lesson, you’ll use similar patterns to build your new endpoints.

Building the Ingredients Endpoint

Let’s start by creating an endpoint that lists all unique ingredients in your database. This will be a GET endpoint, which means users will request data from it.

Step 1: Define the Route

First, you need to define a new route for your endpoint. In your Flask app, you can use a blueprint or the main app object. Here’s how you define the route using a blueprint:

  • @routes.route('/api/ingredients', methods=['GET']) sets up the endpoint at /api/ingredients and only allows GET requests.
Step 2: Query the Database

Next, you want to get all unique ingredient names from the database. You can use SQLAlchemy to do this:

  • db.session.query(Ingredient.name) asks the database for all ingredient names.
  • .distinct() ensures you only get each name once, even if it appears in multiple recipes.
  • .all() returns all results as a list of tuples.
Step 3: Format the Results

The result from the database will look like this: [('egg',), ('flour',), ('milk',)]. You want to return a simple list of strings. You can do this with a list comprehension:

  • [name[0] for name in ingredient_names] extracts the string from each tuple.
  • jsonify(...) turns the list into a JSON response.
  • , 200 sets the HTTP status code to 200 (OK).
Full Example

Here’s the complete endpoint:

Example Output:

If your database has eggs, flour, and milk, a GET request to /api/ingredients will return:

This endpoint is now ready to help users see all available ingredients.

Building the Reviews Endpoint

Now, let’s add a way for users to submit reviews for recipes. This will be a POST endpoint, which means users will send data to it.

Step 1: Define the Route

Set up the route for submitting reviews:

  • This endpoint will accept POST requests at /api/reviews.
Step 2: Get and Validate the Data

You need to get the data the user sends and make sure it’s valid. The user should send a recipe_id and a rating (between 1 and 5).

  • request.get_json() gets the data sent in the request.
  • data.get('recipe_id') and data.get('rating') extract the values.
  • The if statement checks that both values are present and that the rating is between 1 and 5.
  • If the data is invalid, the function returns an error message and a 400 (Bad Request) status.
  • Recipe.query.get(recipe_id) queries the recipe. If we try to submit a review for a non-existant recipe (the recipe variable is None), we will return 404 status.
Step 3: Save the Review

If the data is valid, you can create a new review and save it to the database:

  • Review(recipe_id=recipe_id, rating=rating) creates a new review object.
  • db.session.add(review) adds it to the database session.
  • db.session.commit() saves it to the database.
Step 4: Return a Confirmation

Finally, return a message to let the user know the review was saved:

  • The message confirms the review was saved.
  • The status code 201 means “Created.”
Full Example

Here’s the complete endpoint:

Example Input:

A user might send this JSON to /api/reviews:

Example Output:

If the input is invalid, for example, if the rating is 6:

The output will be:

Summary and Practice Preview

In this lesson, you learned how to add two important features to your smart cooking API: listing all unique ingredients and allowing users to submit reviews for recipes. You saw how to define new endpoints, query the database, validate user input, and return clear JSON responses.

Next, you’ll get a chance to practice what you’ve learned. The upcoming exercises will help you reinforce these skills by guiding you through building and testing similar endpoints on your own. This hands-on practice will ensure you’re comfortable working with Flask routes, database queries, and handling user data. Good luck!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal