Welcome back! So far, you’ve learned how to build API endpoints that let users retrieve recipes, search by ingredients, and view recipe steps. These features are essential for any recipe app, but sometimes users want a little more excitement or guidance. For example, what if someone can’t decide what to cook and wants a random suggestion? Or maybe they want to see the most popular recipes based on ratings from other users.
In this lesson, you’ll learn how to add two new features to your cooking helper API:
- An endpoint that returns a random recipe
- An endpoint that returns the most popular recipes based on user ratings
These features make your app more interactive and helpful, giving users new ways to discover recipes.
Before we dive in, let’s quickly remind ourselves how we’ve been working with recipes so far.
Previously, you built endpoints to:
- List all recipes with pagination (so users don’t get overwhelmed by too many results at once)
- Retrieve a single recipe by its ID
- Search for recipes by ingredients
All of these endpoints use the routing and dependency injection features of the new tool and interact with the database using session objects. You’ve also learned how to format responses as dictionaries, which are automatically converted to JSON.
Now, let’s build on these skills to add dynamic selection features.
Let’s start by creating an endpoint that returns a random recipe. This is useful for users who want to try something new or can’t decide what to cook.
First, we need to define a new route. We’ll use the @router.get decorator to create a GET endpoint at /api/recipes/random.
This sets up the endpoint, but it doesn’t do anything yet.
To select a random recipe from the database, we use the order_by(func.random()) method. This tells the database to shuffle the recipes and pick the first one.
db.query(Recipe)starts a query for all recipes..order_by(func.random())shuffles the order randomly..first()picks the first recipe from the shuffled list.
If there are no recipes in the database, recipe will be None.
Now, let’s check if we found a recipe. If not, we raise an HTTP exception with a 404 status code. If we did, we return the recipe details as a dictionary.
- If no recipe is found, we raise an exception that will return a 404 error.
- Otherwise, we build a dictionary with the recipe’s ID, name, list of ingredient names, and steps.
Here’s the complete function:
Example Output:
This endpoint gives users a fun way to discover new recipes with a single click.
Next, let’s create an endpoint that returns the most popular recipes. We’ll define “popular” as recipes with the highest average user ratings.
We’ll create a GET endpoint at /api/recipes/popular using the @router.get decorator.
To find popular recipes, we need to:
- Calculate the average rating for each recipe
- Sort recipes by their average rating, highest first
- Limit the results to the top 10 recipes
We can do this by creating a subquery that groups reviews by recipe and calculates the average rating.
Review.recipe_idselects all recipe IDs that will be used in the grouping clause.func.avg(Review.rating)calculates the average rating for each recipe..group_by(Review.recipe_id)tells the database to group all the reviews that belong to the same recipe together.
Now, we join this subquery with the Recipe table, sort by average rating, and limit it to 10 results.
.join(subq, Recipe.id == subq.c.recipe_id)links each recipe to its average rating..order_by(subq.c.avg_rating.desc())sorts recipes from highest to lowest average rating..limit(10)returns only the top 10 recipes.
Finally, we build a list of recipes with their details and average ratings.
- For each recipe, we include its ID, name, ingredients, steps, and average rating (rounded to two decimal places).
Here’s the complete function:
Example Output:
This endpoint helps users quickly find the best-rated recipes, making it easier to choose something delicious.
In this lesson, you learned how to add two new endpoints to your recipe API:
- One for serving a random recipe to help users discover new dishes
- One for listing the most popular recipes based on user ratings
These features make your app more dynamic and user-friendly. Now, you’re ready to practice building and using these endpoints in the exercises that follow. This will help you reinforce what you’ve learned and see how these features work in real scenarios.
Keep up the great work — your cooking helper app is becoming more powerful with each lesson!
