Let's build Restaurant API using modern Python and FastAPI as the web framework.
This is what we are going to implement today!
A simple backend service which stores information about restaurants and has two endpoints for accessing that information:
- GET /restaurants which returns data for all the restaurants.The response payload format should be:
[
{
"name": "Example restaurant",
"description": "Example description",
"id": "unique-id-for-the-restaurant",
"location": {
"city": "Example city",
"coordinates": {
"lat": 60.169938852212965,
"lon": 24.941325187683105
}
}
}
]
- GET /restaurants/(restaurant-id) which returns data for a single restaurant. The response payload format should be:
{
"name": "Example restaurant",
"description": "Example description",
"id": "unique-id-for-the-restaurant",
"location": {
"city": "Example city",
"coordinates": {
"lat": 60.169938852212965,
"lon": 24.941325187683105
}
}
}
The restaurant data is stored in the restaurants.json file which contains information about 20 imaginary restaurants which are located in Helsinki area.
Example data for a single restaurant:
{
"blurhash": "UUKJMXv|x]oz0gtRM{V@AHRQwvxZXSs9s;o0",
"city": "Helsinki",
"description": "Burgers with attitude!",
"id": "456162c4-8dab-4959-8cdd-3777c7ede20d",
"image": "https://prod-wolt-venue-images-cdn.wolt.com/5b348b31fe8992000bbec771/2be8c7738b220df2f9a0974da5c90d90",
"location": [
24.941325187683105,
60.169938852212965
],
"name": "Burger plaza",
"tags": [
"hamburger",
"fries"
]
}
Fields:
- blurhash: A compact representation of a placeholder for an image (type: string), see https://blurha.sh/.
- city: A city where the restaurant is located (type: string)
- description: More information about what kind of restaurant it is (type: string)
- id: Unique identifier for the restaurant (type: string)
- image: A link to restaurant's image (type: string)
- location: Restaurant's location in latitude & longitude coordinates. First element in the list is the longitude (type: a list containing two numbers)
- name: The name of the restaurant (type: string)
- tags: A list of tags describing what kind of food the restaurant sells, e.g. pizza / burger (type: a list of strings, max. 3 elements)
Run the app:
docker compose up
The API documentation is available in http://127.0.0.1:8000/docs.
docker compose run restaurant-api pytest
Prerequisites
- Python 3.10 or later: https://www.python.org/downloads/
Create a virtual environment:
python -m venv .venv
Activate the virtual environment:
-
Linux / MacOS:
source .venv/bin/activate
-
Windows (CMD):
.venv/Scripts/activate.bat
-
Windows (Powershell)
.venv/Scripts/Activate.ps1
Install the dependencies
pip install -r requirements.txt
Run the server (--reload
automatically restarts the server when there are changes in the code):
uvicorn app.main:app --reload
The API documentation is available in http://127.0.0.1:8000/docs.
pytest
You can code these on your own after the workshop 😉
- Implement an endpoint which lists all the restaurants for a given tag. For example: GET /restaurants/tags/hamburger
- Implement a search endpoint which takes a search string as a query parameter and returns the restaurants which have a full or a partial match for the search string in their name, description or tags fields. For example: GET /restaurants/search?q=sushi
- Implement an endpoint which takes the customer location as a query parameter and returns the restaurants which are within 500 meters radius from the customer's location. For example: GET /restaurants/nearby?lat=60.17106&lon=24.934434
- Instead of storing the restaurants in a static json file, store them in a database instead (hint: have a look at SQLModel). Additionally add endpoints for creating, updating, and deleting restaurants.
- Implement automated tests for all the functionality you've built. Familiarise yourself with pytest and read how to test FastAPI applications.
- Poetry for dependency management
- Ruff for linting
- Ruff Formatter for automatic formatting
- Mypy for static type checking
- Pre-commit for automatically running all the code quality related tools during commits/pushes
- pytest-cov for measuring the test coverage
- GitHub Actions for continuous integration