1. Introduction
In this tutorial, you will learn how to use different types of parameters to pass data to your web API using FastAPI, a modern and fast web framework for Python. Parameters are essential for creating dynamic and interactive web applications, as they allow you to customize the behavior and output of your API based on the user’s input.
There are three main types of parameters that you can use in FastAPI: path parameters, query parameters, and request body parameters. Each type of parameter has its own advantages and use cases, and you will see how to define and validate them using FastAPI and Pydantic models.
By the end of this tutorial, you will be able to:
- Create a simple web API with FastAPI and run it locally.
- Use path parameters to define dynamic parts of the URL path.
- Use query parameters to pass optional or extra information to the API.
- Use request body parameters to send complex or structured data to the API.
- Use Pydantic models to validate and document the parameters and the response.
To follow this tutorial, you will need:
- Python 3.6 or higher installed on your machine.
- A code editor of your choice.
- A basic understanding of Python and web development.
Ready to get started? Let’s dive in!
2. What are Path Parameters?
Path parameters are one of the most common types of parameters that you can use in web APIs. They are used to define dynamic parts of the URL path that can vary depending on the user’s input. For example, if you have a web API that returns information about different products, you can use a path parameter to specify the product ID in the URL, such as https://example.com/products/123
. In this case, 123
is the path parameter that represents the product ID.
Path parameters are useful for creating RESTful web APIs that follow a hierarchical structure of resources and subresources. They allow you to access and manipulate specific resources based on their identifiers. For example, you can use path parameters to create CRUD (Create, Read, Update, Delete) operations for your web API, such as GET /products/123
to read a product, POST /products
to create a new product, PUT /products/123
to update a product, and DELETE /products/123
to delete a product.
However, path parameters also have some limitations and challenges. For instance, they are mandatory and positional, meaning that you have to provide them in the exact order and number that the web API expects. If you omit or change the order of the path parameters, you will get an error or a different result. Moreover, path parameters are usually limited to simple data types, such as integers or strings, and they cannot contain special characters or spaces. If you want to pass more complex or optional data to your web API, you will need to use other types of parameters, such as query parameters or request body parameters.
In the next sections, you will learn how to define and validate path parameters in FastAPI using Pydantic models. You will also see how to use path parameters to create a simple web API that returns information about different books.
2.1. How to Define Path Parameters in FastAPI
To define path parameters in FastAPI, you need to use the Path
function from the fastapi
module. The Path
function allows you to specify the name, type, and default value of the path parameter, as well as other optional arguments, such as validation rules, documentation, and dependencies. You can also use type annotations to declare the type of the path parameter, such as int
, str
, or float
.
For example, let’s say you want to create a web API that returns information about different books based on their ISBN. You can use a path parameter to represent the ISBN of the book in the URL, such as https://example.com/books/978-3-16-148410-0
. To define the path parameter, you can use the following code:
from fastapi import FastAPI, Path app = FastAPI() @app.get("/books/{isbn}") def get_book(isbn: str = Path(...)): # your code here
In this code, you are using the @app.get
decorator to create a GET endpoint for the /books/{isbn}
path. The {isbn}
part indicates that this is a path parameter, and you can access its value in the function parameter with the same name. The isbn: str = Path(...)
part declares that the type of the path parameter is a string, and that it is required (the ...
means that there is no default value). You can also use the Path
function to add more arguments, such as a description, an example, or a regex pattern for validation.
Now, you can use the isbn
parameter to query your database or perform some logic to return the information about the book. For example, you can use a simple dictionary to store some sample data, and return it as a JSON response:
from fastapi import FastAPI, Path app = FastAPI() # sample data books = { "978-3-16-148410-0": { "title": "The Hitchhiker's Guide to the Galaxy", "author": "Douglas Adams", "year": 1979 }, "978-0-14-032872-1": { "title": "Matilda", "author": "Roald Dahl", "year": 1988 }, "978-0-385-08108-8": { "title": "The Catcher in the Rye", "author": "J.D. Salinger", "year": 1951 } } @app.get("/books/{isbn}") def get_book(isbn: str = Path(...)): # check if the isbn exists in the data if isbn in books: # return the book data as a JSON response return books[isbn] else: # return an error message return {"error": "Book not found"}
Now, you can test your web API by running it locally and sending requests to the /books/{isbn}
endpoint with different ISBN values. You should see the corresponding book data or an error message in the response.
2.2. How to Validate Path Parameters with Pydantic Models
One of the benefits of using FastAPI is that it automatically validates the parameters and the response of your web API using Pydantic models. Pydantic is a library that allows you to define data models with type annotations and perform data validation, parsing, and serialization. FastAPI integrates with Pydantic to provide type checking, data conversion, and documentation for your web API.
To validate path parameters with Pydantic models, you need to use the Path
function from the fastapi
module and pass the Pydantic model as the first argument. The Pydantic model defines the type, constraints, and default value of the path parameter, as well as other optional arguments, such as description, example, or regex pattern. You can also use type annotations to declare the type of the path parameter, such as int
, str
, or float
.
For example, let’s say you want to validate the ISBN path parameter that you defined in the previous section. You can use a Pydantic model to specify that the ISBN must be a string of 13 digits, starting with 978 or 979, and separated by hyphens. You can also provide a description and an example for the documentation. To validate the path parameter, you can use the following code:
from fastapi import FastAPI, Path from pydantic import BaseModel app = FastAPI() # define a Pydantic model for the ISBN class ISBN(BaseModel): isbn: str = Path( ..., title="ISBN", description="The International Standard Book Number of the book", example="978-3-16-148410-0", regex=r"^(978|979)-\d{1,5}-\d{1,7}-\d{1,6}-\d$" ) # sample data books = { "978-3-16-148410-0": { "title": "The Hitchhiker's Guide to the Galaxy", "author": "Douglas Adams", "year": 1979 }, "978-0-14-032872-1": { "title": "Matilda", "author": "Roald Dahl", "year": 1988 }, "978-0-385-08108-8": { "title": "The Catcher in the Rye", "author": "J.D. Salinger", "year": 1951 } } @app.get("/books/{isbn}") def get_book(isbn: ISBN): # check if the isbn exists in the data if isbn.isbn in books: # return the book data as a JSON response return books[isbn.isbn] else: # return an error message return {"error": "Book not found"}
In this code, you are using the ISBN
class to define a Pydantic model for the ISBN path parameter. The isbn: str = Path(...)
part declares that the type of the path parameter is a string, and that it is required (the ...
means that there is no default value). You can also use the Path
function to add more arguments, such as a title, a description, an example, and a regex pattern for validation. The regex pattern ensures that the ISBN follows the format of 13 digits, starting with 978 or 979, and separated by hyphens.
Now, you can use the isbn
parameter to query your database or perform some logic to return the information about the book. However, since the isbn
parameter is now an instance of the ISBN
class, you need to access its isbn
attribute to get the actual value of the ISBN. For example, you can use isbn.isbn
to check if the ISBN exists in the data, and to return the book data as a JSON response.
Now, you can test your web API by running it locally and sending requests to the /books/{isbn}
endpoint with different ISBN values. You should see the corresponding book data or an error message in the response. If you send an invalid ISBN value, such as one that does not match the regex pattern, you should see a validation error in the response.
3. What are Query Parameters?
Query parameters are another type of parameters that you can use in web APIs. They are used to pass optional or extra information to the API that is not part of the URL path. For example, if you have a web API that returns a list of books, you can use query parameters to filter, sort, or paginate the results, such as https://example.com/books?author=Douglas+Adams&limit=10
. In this case, author
and limit
are query parameters that specify the criteria and the number of books to return.
Query parameters are useful for creating flexible and customizable web APIs that can handle different user preferences and scenarios. They allow you to modify the behavior and output of your API based on the user’s input. For example, you can use query parameters to implement features such as search, filtering, sorting, pagination, authentication, or caching for your web API.
However, query parameters also have some limitations and challenges. For instance, they are optional and non-positional, meaning that you can provide them in any order and number, or omit them entirely. This can make the web API more complex and harder to test, as you have to account for all the possible combinations and cases of query parameters. Moreover, query parameters are usually limited to simple data types, such as integers, strings, or booleans, and they cannot contain complex or structured data, such as lists, dictionaries, or objects. If you want to pass more complex or required data to your web API, you will need to use other types of parameters, such as path parameters or request body parameters.
In the next sections, you will learn how to define and validate query parameters in FastAPI using Pydantic models. You will also see how to use query parameters to create a simple web API that returns a list of books with different criteria.
3.1. How to Define Query Parameters in FastAPI
To define query parameters in FastAPI, you need to use the Query
function from the fastapi
module. The Query
function allows you to specify the name, type, and default value of the query parameter, as well as other optional arguments, such as validation rules, documentation, and dependencies. You can also use type annotations to declare the type of the query parameter, such as int
, str
, or bool
.
For example, let’s say you want to create a web API that returns a list of books with different criteria based on the query parameters. You can use query parameters to filter the books by author, genre, or year, and to limit the number of books to return. To define the query parameters, you can use the following code:
from fastapi import FastAPI, Query app = FastAPI() @app.get("/books") def get_books( author: str = Query(None), genre: str = Query(None), year: int = Query(None), limit: int = Query(10) ): # your code here
In this code, you are using the @app.get
decorator to create a GET endpoint for the /books
path. The function parameters represent the query parameters that you can pass to the endpoint, and you can access their values in the function body. The author: str = Query(None)
part declares that the author
query parameter is a string, and that it is optional (the None
means that there is no default value). You can also use the Query
function to add more arguments, such as a description, an example, or a validation rule. The same applies to the genre
and year
query parameters. The limit: int = Query(10)
part declares that the limit
query parameter is an integer, and that it has a default value of 10. You can also use the Query
function to specify a minimum and a maximum value for the limit
query parameter.
Now, you can use the query parameters to query your database or perform some logic to return the list of books that match the criteria. For example, you can use a simple list to store some sample data, and filter it based on the query parameters. You can also use the limit
query parameter to slice the list and return only the specified number of books. You can use the following code:
from fastapi import FastAPI, Query app = FastAPI() # sample data books = [ { "title": "The Hitchhiker's Guide to the Galaxy", "author": "Douglas Adams", "genre": "Science Fiction", "year": 1979 }, { "title": "Matilda", "author": "Roald Dahl", "genre": "Children's Literature", "year": 1988 }, { "title": "The Catcher in the Rye", "author": "J.D. Salinger", "genre": "Coming-of-Age", "year": 1951 }, { "title": "The Lord of the Rings", "author": "J.R.R. Tolkien", "genre": "Fantasy", "year": 1954 }, { "title": "Nineteen Eighty-Four", "author": "George Orwell", "genre": "Dystopian", "year": 1949 } ] @app.get("/books") def get_books( author: str = Query(None), genre: str = Query(None), year: int = Query(None), limit: int = Query(10, ge=1, le=100) ): # filter the books based on the query parameters filtered_books = [book for book in books if (author is None or book["author"] == author) and (genre is None or book["genre"] == genre) and (year is None or book["year"] == year) ] # return the filtered books as a JSON response, limited by the limit query parameter return filtered_books[:limit]
Now, you can test your web API by running it locally and sending requests to the /books
endpoint with different query parameters. You should see the list of books that match the criteria in the response. If you omit or provide invalid query parameters, you should see the default or error behavior in the response.
3.2. How to Validate Query Parameters with Pydantic Models
One of the benefits of using FastAPI is that it automatically validates the parameters and the response of your web API using Pydantic models. Pydantic is a library that allows you to define data models with type annotations and perform data validation, parsing, and serialization. FastAPI integrates with Pydantic to provide type checking, data conversion, and documentation for your web API.
To validate query parameters with Pydantic models, you need to use the Query
function from the fastapi
module and pass the Pydantic model as the first argument. The Pydantic model defines the type, constraints, and default value of the query parameter, as well as other optional arguments, such as description, example, or regex pattern. You can also use type annotations to declare the type of the query parameter, such as int
, str
, or bool
.
For example, let’s say you want to validate the limit
query parameter that you defined in the previous section. You can use a Pydantic model to specify that the limit
must be an integer between 1 and 100, and that it has a default value of 10. You can also provide a description and an example for the documentation. To validate the query parameter, you can use the following code:
from fastapi import FastAPI, Query from pydantic import BaseModel app = FastAPI() # define a Pydantic model for the limit class Limit(BaseModel): limit: int = Query( 10, title="Limit", description="The number of books to return", example=10, ge=1, le=100 ) # sample data books = [ { "title": "The Hitchhiker's Guide to the Galaxy", "author": "Douglas Adams", "genre": "Science Fiction", "year": 1979 }, { "title": "Matilda", "author": "Roald Dahl", "genre": "Children's Literature", "year": 1988 }, { "title": "The Catcher in the Rye", "author": "J.D. Salinger", "genre": "Coming-of-Age", "year": 1951 }, { "title": "The Lord of the Rings", "author": "J.R.R. Tolkien", "genre": "Fantasy", "year": 1954 }, { "title": "Nineteen Eighty-Four", "author": "George Orwell", "genre": "Dystopian", "year": 1949 } ] @app.get("/books") def get_books( author: str = Query(None), genre: str = Query(None), year: int = Query(None), limit: Limit ): # filter the books based on the query parameters filtered_books = [book for book in books if (author is None or book["author"] == author) and (genre is None or book["genre"] == genre) and (year is None or book["year"] == year) ] # return the filtered books as a JSON response, limited by the limit query parameter return filtered_books[:limit.limit]
In this code, you are using the Limit
class to define a Pydantic model for the limit
query parameter. The limit: int = Query(10)
part declares that the type of the query parameter is an integer, and that it has a default value of 10. You can also use the Query
function to add more arguments, such as a title, a description, an example, and a minimum and maximum value for validation. The minimum and maximum values ensure that the limit
is between 1 and 100.
Now, you can use the limit
parameter to query your database or perform some logic to return the list of books that match the criteria. However, since the limit
parameter is now an instance of the Limit
class, you need to access its limit
attribute to get the actual value of the limit. For example, you can use limit.limit
to slice the list and return only the specified number of books.
Now, you can test your web API by running it locally and sending requests to the /books
endpoint with different query parameters. You should see the list of books that match the criteria in the response. If you omit or provide invalid query parameters, you should see the default or error behavior in the response.
4. What are Request Body Parameters?
Request body parameters are another type of parameters that you can use in web APIs. They are used to pass complex or structured data to the API that is not part of the URL path or the query string. For example, if you have a web API that allows you to create or update a book, you can use request body parameters to send the details of the book, such as the title, author, genre, and year, as a JSON object in the body of the request.
Request body parameters are useful for creating web APIs that can handle different types of data and operations, such as creating, updating, or deleting resources. They allow you to send and receive data that is not limited by the URL format or the simple data types. For example, you can use request body parameters to implement features such as authentication, file upload, or data analysis for your web API.
However, request body parameters also have some limitations and challenges. For instance, they are only available for certain HTTP methods, such as POST, PUT, PATCH, or DELETE, and not for GET or HEAD. This means that you cannot use request body parameters to retrieve data from your web API, only to send data to it. Moreover, request body parameters are usually hidden from the user, as they are not visible in the URL or the browser. This can make the web API more difficult to debug and test, as you have to inspect the request and the response to see the data.
In the next sections, you will learn how to define and validate request body parameters in FastAPI using Pydantic models. You will also see how to use request body parameters to create a simple web API that allows you to create and update books.
4.1. How to Define Request Body Parameters in FastAPI
To define request body parameters in FastAPI, you need to use the Body
function from the fastapi
module and pass the Pydantic model as the first argument. The Pydantic model defines the type, constraints, and default value of the request body parameter, as well as other optional arguments, such as description, example, or alias. You can also use type annotations to declare the type of the request body parameter, such as dict
, list
, or BaseModel
.
For example, let’s say you want to create a web API that allows you to create or update a book. You can use a request body parameter to send the details of the book, such as the title, author, genre, and year, as a JSON object in the body of the request. To define the request body parameter, you can use the following code:
from fastapi import FastAPI, Body from pydantic import BaseModel app = FastAPI() # define a Pydantic model for the book class Book(BaseModel): title: str author: str genre: str year: int @app.post("/books") def create_book(book: Book = Body(...)): # your code here
In this code, you are using the @app.post
decorator to create a POST endpoint for the /books
path. The book: Book = Body(...)
part declares that the request body parameter is an instance of the Book
class, and that it is required (the ...
means that there is no default value). The Book
class defines a Pydantic model for the book, with four attributes: title
, author
, genre
, and year
. You can also use the Body
function to add more arguments, such as a description, an example, or an alias.
Now, you can use the book
parameter to query your database or perform some logic to create or update the book. For example, you can use a simple list to store the books, and append the new book to the list. You can also return the new book as a JSON response:
from fastapi import FastAPI, Body from pydantic import BaseModel app = FastAPI() # define a Pydantic model for the book class Book(BaseModel): title: str author: str genre: str year: int # sample data books = [] @app.post("/books") def create_book(book: Book = Body(...)): # append the new book to the list books.append(book) # return the new book as a JSON response return book
Now, you can test your web API by running it locally and sending requests to the /books
endpoint with different book details in the body of the request. You should see the new book in the response. If you omit or provide invalid request body parameters, you should see the error behavior in the response.
4.2. How to Validate Request Body Parameters with Pydantic Models
One of the benefits of using FastAPI is that it automatically validates the parameters and the response of your web API using Pydantic models. Pydantic is a library that allows you to define data models with type annotations and perform data validation, parsing, and serialization. FastAPI integrates with Pydantic to provide type checking, data conversion, and documentation for your web API.
To validate request body parameters with Pydantic models, you need to use the Body
function from the fastapi
module and pass the Pydantic model as the first argument. The Pydantic model defines the type, constraints, and default value of the request body parameter, as well as other optional arguments, such as description, example, or alias. You can also use type annotations to declare the type of the request body parameter, such as dict
, list
, or BaseModel
.
For example, let’s say you want to validate the book
request body parameter that you defined in the previous section. You can use a Pydantic model to specify that the book
must have four attributes: title
, author
, genre
, and year
, and that they are all required and of type str
or int
. You can also provide a description and an example for the documentation. To validate the request body parameter, you can use the following code:
from fastapi import FastAPI, Body from pydantic import BaseModel app = FastAPI() # define a Pydantic model for the book class Book(BaseModel): title: str author: str genre: str year: int class Config: schema_extra = { "description": "A book object", "example": { "title": "The Hitchhiker's Guide to the Galaxy", "author": "Douglas Adams", "genre": "Science Fiction", "year": 1979 } } @app.post("/books") def create_book(book: Book = Body(...)): # your code here
In this code, you are using the Book
class to define a Pydantic model for the book
request body parameter. The class attributes declare the type and the required status of the book attributes. You can also use the Config
class to add extra information to the schema, such as a description and an example. The book: Book = Body(...)
part declares that the request body parameter is an instance of the Book
class, and that it is required (the ...
means that there is no default value).
Now, you can use the book
parameter to query your database or perform some logic to create or update the book. For example, you can use a simple list to store the books, and append the new book to the list. You can also return the new book as a JSON response:
from fastapi import FastAPI, Body from pydantic import BaseModel app = FastAPI() # define a Pydantic model for the book class Book(BaseModel): title: str author: str genre: str year: int class Config: schema_extra = { "description": "A book object", "example": { "title": "The Hitchhiker's Guide to the Galaxy", "author": "Douglas Adams", "genre": "Science Fiction", "year": 1979 } } # sample data books = [] @app.post("/books") def create_book(book: Book = Body(...)): # append the new book to the list books.append(book) # return the new book as a JSON response return book
Now, you can test your web API by running it locally and sending requests to the /books
endpoint with different book details in the body of the request. You should see the new book in the response. If you omit or provide invalid request body parameters, you should see the error behavior in the response.
5. Conclusion
In this tutorial, you learned how to use different types of parameters to pass data to your web API using FastAPI, a modern and fast web framework for Python. You learned how to define and validate path parameters, query parameters, and request body parameters using FastAPI and Pydantic models. You also learned how to use these parameters to create a simple web API that returns information about different books.
By using parameters, you can create dynamic and interactive web applications that can customize the behavior and output of your web API based on the user’s input. Parameters are essential for creating RESTful web APIs that follow a hierarchical structure of resources and subresources. They also allow you to handle different types of data and operations, such as creating, updating, or deleting resources.
However, parameters also have some limitations and challenges, such as being mandatory and positional, being limited to simple data types, or being hidden from the user. Therefore, you need to choose the appropriate type of parameter for your web API, and use the validation and documentation features of FastAPI and Pydantic to ensure the quality and reliability of your web API.
FastAPI is a powerful and easy-to-use web framework that provides many features and benefits for web development, such as automatic documentation, dependency injection, and testing tools. If you want to learn more about FastAPI, you can check out the official documentation or the GitHub repository.
We hope you enjoyed this tutorial and found it useful. If you have any questions or feedback, feel free to leave a comment below. Happy coding!