Adding Ingredients and Reviews
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. Now, we are going to make your cooking 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 using a modern API framework.
Quick Recall: API Endpoints Refresher
Before we dive in, let’s quickly remind ourselves how endpoints work in this framework. Instead of defining the URL and the logic in the same place, we split them into two files:
urls.py: This file handles routing. It maps a URL path (like/hello) to a specific function.views.py: This file contains the logic. It defines functions (called "views") that take arequestand return a response.
To restrict which HTTP methods (like GET or POST) an endpoint accepts, we use decorators like @require_http_methods.
For example, here’s a simple GET endpoint:
urls.py
views.py
In this lesson, you’ll use this pattern 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 and View
First, you need to define the function in views.py and map it to a path in urls.py. The view function always takes a request object as its first argument.
views.py
urls.py
Step 2: Query the Database
Next, you want to get all unique ingredient names from the database. You can use the ORM (Object-Relational Mapper) to do this efficiently:
Ingredient.objects.values_list("name", flat=True)asks the database for just the values of thenamecolumn..distinct()ensures you only get each name once.
Step 3: Format the Results
The ORM query returns a special QuerySet object. To return this as a JSON response, we convert it into a standard list.
list(names)converts the database result into a simple list of strings.safe=Falseis required inJsonResponsewhenever you are returning a list (an array) instead of a dictionary (an object) at the top level.
Full Example
Here is how the implementation looks across your files:
recipes/urls.py
recipes/views.py
Example Output:
If your database has eggs, flour, and milk, a GET request to /ingredients will return:
Building the Reviews Endpoint
Now, let’s add a way for users to submit reviews for recipes. This will be a POST endpoint. Because we are receiving data, we need to handle manual JSON parsing and security.
Step 1: Define the Route and Decorators
To handle a POST request for data submission, we use two important decorators:
@csrf_exempt: This allows external tools or frontends to sendPOSTrequests to our API without needing a security token (common for purely programmatic APIs).@require_http_methods(["POST"]): This ensures the endpoint only reacts toPOSTrequests.
Step 2: Get and Validate the Data
Since the data is sent in the request body as JSON, we must parse it manually. We also need to check if the user provided the required fields and if the rating is within the valid range (1 to 5).
We also check whether the recipe being reviewed actually exists in our database:
.filter(pk=recipe_id).first()looks for a recipe where the primary key matches theID. If none is found, it returnsNone.
Step 3: Save the Review and Return Confirmation
If the data is valid, we create a new record in the database and return a 201 Created status code.
Review.objects.create()builds and saves the object in one step.status=201explicitly tells the user that a new resource was created.
Full Example
Here is the complete implementation for the reviews endpoint, including a helper for parsing:
recipes/views.py
Example Input:
A user sends this JSON to /reviews:
Example Output:
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. You saw how to:
- Map
URLsinurls.pyto logic inviews.py. - Use
ORMmethods likevalues_listanddistinct. - Manually parse
JSONfrom arequestbody and perform validation. - Return appropriate status codes like
201for created resources and422or400for errors.
Next, you’ll get a chance to practice these skills by building and testing similar endpoints on your own!
