FastAPI Tutorial: A Quick Guide
Hey guys! So you're looking to dive into the world of FastAPI, huh? Awesome! FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.7+ based on standard Python type hints. It's quickly becoming a favorite among developers because of its speed, ease of use, and automatic data validation. This tutorial will guide you through the essentials, so you can start building your own APIs in no time!
What is FastAPI?
FastAPI, at its core, is a Python web framework designed for building APIs. But it's not just any framework. It's built with performance in mind, leveraging asynchronous programming to handle requests concurrently. This means your API can handle more traffic without slowing down. But the real magic lies in its use of Python type hints. By declaring the expected data types for your API endpoints, FastAPI can automatically validate incoming data, serialize responses, and even generate API documentation! How cool is that?
Let's break down why FastAPI is so popular:
- Speed: Built on top of Starlette and Uvicorn, FastAPI offers impressive performance, rivaling Node.js and Go.
- Ease of Use: Its intuitive design and reliance on Python type hints make it easy to learn and use, even for beginners.
- Automatic Data Validation: FastAPI automatically validates incoming data based on your type hints, saving you time and effort.
- Automatic API Documentation: It generates interactive API documentation using OpenAPI and Swagger UI, making it easy for others to understand and use your API.
- Dependency Injection: FastAPI has a powerful dependency injection system, making your code more modular and testable.
Setting Up Your Environment
Before we start coding, let's get your environment set up. You'll need Python 3.7+ installed on your system. If you don't have it already, head over to the official Python website and download the latest version. Once you have Python installed, you can use pip, the Python package installer, to install FastAPI and Uvicorn.
-
Create a Virtual Environment: It's always a good idea to create a virtual environment for your projects. This helps to isolate your project's dependencies from other projects on your system. Open your terminal and navigate to your project directory. Then, run the following command:
python3 -m venv venv -
Activate the Virtual Environment:
-
On macOS and Linux:
source venv/bin/activate -
On Windows:
.\venv\Scripts\activate
-
-
Install FastAPI and Uvicorn: Now that your virtual environment is activated, you can install FastAPI and Uvicorn using pip:
pip install fastapi uvicornFastAPI is the framework itself, and Uvicorn is an ASGI (Asynchronous Server Gateway Interface) server that will run your API.
Creating Your First API
Alright, let's get our hands dirty and create a simple API endpoint. Create a new file named main.py and open it in your favorite text editor. Now, let's add some code:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
Let's break down what's happening here:
from fastapi import FastAPI: This line imports theFastAPIclass from thefastapilibrary.app = FastAPI(): This creates an instance of theFastAPIclass, which we'll use to define our API endpoints.@app.get("/"): This is a decorator that tells FastAPI that the function below it should handle GET requests to the root path ("/").async def read_root(): This defines an asynchronous function namedread_root. Theasynckeyword means that this function can run concurrently with other functions, improving performance.return {"Hello": "World"}: This returns a JSON response with a single key-value pair:{"Hello": "World"}.
To run your API, open your terminal and navigate to the directory where you saved main.py. Then, run the following command:
uvicorn main:app --reload
main: This specifies the name of the Python file containing your API.app: This specifies the name of theFastAPIinstance in your code.--reload: This tells Uvicorn to automatically reload the server whenever you make changes to your code.
Now, open your web browser and go to http://127.0.0.1:8000. You should see the {"Hello": "World"} JSON response in your browser. Congrats! You've just created your first FastAPI endpoint.
Adding More Endpoints
Okay, so returning "Hello World" is cool and all, but let's add some more interesting endpoints to our API. Let's create an endpoint that accepts a name as a parameter and returns a personalized greeting.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
Let's break down the new code:
@app.get("/items/{item_id}"): This defines a new endpoint that handles GET requests to the/items/{item_id}path. The{item_id}part is a path parameter, which means that it can be different for each request. FastAPI will automatically extract the value of theitem_idparameter and pass it to theread_itemfunction.async def read_item(item_id: int, q: str = None): This defines an asynchronous function namedread_item. It takes two parameters:item_idandq. Theitem_idparameter is annotated withint, which tells FastAPI that it should be an integer. Theqparameter is a query parameter, which means that it's optional and can be passed in the URL after a?. Theq: str = Nonepart means that theqparameter is a string and has a default value ofNoneif it's not provided.return {"item_id": item_id, "q": q}: This returns a JSON response with theitem_idandqvalues.
Now, restart your server and go to http://127.0.0.1:8000/items/123?q=hello. You should see the {"item_id": 123, "q": "hello"} JSON response in your browser. If you go to http://127.0.0.1:8000/items/123, you should see the {"item_id": 123, "q": null} JSON response.
Data Validation
One of the coolest features of FastAPI is its automatic data validation. By using Python type hints, you can tell FastAPI what data types to expect for your API endpoints. If the incoming data doesn't match the expected types, FastAPI will automatically return an error response.
Let's add some data validation to our read_item endpoint. We'll make the item_id parameter required and ensure that it's an integer.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
Now, if you try to go to http://127.0.0.1:8000/items/abc, you'll see an error response because abc is not an integer.
Using Pydantic Models
For more complex data structures, you can use Pydantic models. Pydantic is a data validation and settings management library that integrates seamlessly with FastAPI. To use Pydantic, you'll need to install it:
pip install pydantic
Let's create a Pydantic model for our items. We'll define the name, description, and price attributes for each item.
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str = None
price: float
tax: float = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
item_dict = item.dict()
if item.tax:
price_with_tax = item.price + item.tax
item_dict.update({"price_with_tax": price_with_tax})
return item_dict
Let's break down the new code:
from pydantic import BaseModel: This imports theBaseModelclass from thepydanticlibrary.class Item(BaseModel): This defines a new class namedItemthat inherits fromBaseModel. This means thatItemis a Pydantic model.name: str: This defines an attribute namednameof typestr. This means that thenameattribute must be a string.description: str = None: This defines an attribute nameddescriptionof typestrwith a default value ofNone. This means that thedescriptionattribute is optional and can be a string orNone.price: float: This defines an attribute namedpriceof typefloat. This means that thepriceattribute must be a float.tax: float = None: This defines an attribute namedtaxof typefloatwith a default value ofNone. This means that thetaxattribute is optional and can be a float orNone.@app.post("/items/"): This defines a new endpoint that handles POST requests to the/items/path. This endpoint will be used to create new items.async def create_item(item: Item): This defines an asynchronous function namedcreate_item. It takes a single parameter:item, which is an instance of theItemmodel. FastAPI will automatically validate the incoming data and create anIteminstance from it.item_dict = item.dict(): This converts theIteminstance to a dictionary.- The rest of the code calculates the price with tax and returns a dictionary with the item information.
To test this endpoint, you can use a tool like Postman or curl. Send a POST request to http://127.0.0.1:8000/items/ with the following JSON payload:
{
"name": "Foo",
"description": "A very nice Item",
"price": 50.2,
"tax": 3.2
}
You should get a response like this:
{
"name": "Foo",
"description": "A very nice Item",
"price": 50.2,
"tax": 3.2,
"price_with_tax": 53.4
}
Automatic API Documentation
One of the best things about FastAPI is its automatic API documentation. FastAPI automatically generates interactive API documentation using OpenAPI and Swagger UI. To view the documentation, open your web browser and go to http://127.0.0.1:8000/docs. You should see the Swagger UI, which allows you to explore your API endpoints, try them out, and see the request and response schemas.
You can also access the OpenAPI schema in JSON format by going to http://127.0.0.1:8000/openapi.json. This is useful for integrating your API with other tools and services.
Conclusion
Alright, guys, that's it for this FastAPI tutorial! You've learned the basics of FastAPI, including how to create API endpoints, validate data, use Pydantic models, and generate automatic API documentation. Now you're ready to start building your own awesome APIs with FastAPI. Go forth and create!