|
| 1 | + |
| 2 | +# FastAPI |
| 3 | + |
| 4 | + |
| 5 | +## Table of Contents |
| 6 | + |
| 7 | +- [Introduction](#introduction) |
| 8 | +- [Features](#features) |
| 9 | +- [Installation](#installation) |
| 10 | +- [Making First API](#making-first-api) |
| 11 | + - [GET Method](#get-method) |
| 12 | + - [Running Server and calling API](#running-server-and-calling-api) |
| 13 | +- [Path Parameters](#pata-parameters) |
| 14 | +- [Query Parameters](#query-parameters) |
| 15 | +- [POST Method](#post-method) |
| 16 | +- [PUT Method](#put-method) |
| 17 | +- [Additional Content](#additional-content) |
| 18 | + - [Swagger UI](#swagger-ui) |
| 19 | + |
| 20 | +## Introduction |
| 21 | +FastAPI is a modern, web-framework for building APIs with Python. |
| 22 | +It uses python 3.7+ |
| 23 | +## Features |
| 24 | + |
| 25 | +1. **Speed ⚡:** FastAPI is built on top of Starlette, a lightweight ASGI framework. It's designed for high performance and handles thousands of requests per second . |
| 26 | +2. **Easy to use 😃:** FastAPI is designed to be intuitive and easy to use, especially for developers familiar with Python. It uses standard Python type hints for request and response validation, making it easy to understand and write code. |
| 27 | +3. **Automatic Interactive API Documentation generation 🤩:** FastAPI automatically generates interactive API documentation (Swagger UI or ReDoc) based on your code and type annotations. Swagger UI also allows you to test API endpoints. |
| 28 | +4. **Asynchronous Support 🔁:** FastAPI fully supports asynchronous programming, allowing you to write asynchronous code with async/await syntax. This enables handling high-concurrency scenarios and improves overall performance. |
| 29 | + |
| 30 | +Now, lets get hands-on with FastAPI. |
| 31 | + |
| 32 | + |
| 33 | +## Installation |
| 34 | + |
| 35 | +Make sure that you have python version 3.7 or greater. |
| 36 | + |
| 37 | +Then, simply open your command shell and give the following command. |
| 38 | + |
| 39 | +```bash |
| 40 | + pip install fastapi |
| 41 | +``` |
| 42 | +After this, you need to install uvicorn. uvicorn is an ASGI server on which we will be running our API. |
| 43 | + |
| 44 | +```bash |
| 45 | + pip install uvicorn |
| 46 | +``` |
| 47 | + |
| 48 | + |
| 49 | + |
| 50 | +## Making First API |
| 51 | + |
| 52 | +After successful installation we will be moving towards making an API and seeing how to use it. |
| 53 | + |
| 54 | +Firstly, the first thing in an API is its root/index page which is sent as response when API is called. |
| 55 | + |
| 56 | +Follow the given steps to make your first FastAPI🫨 |
| 57 | + |
| 58 | +First, lets import FastAPI to get things started. |
| 59 | + |
| 60 | +```python |
| 61 | +from fastapi import FastAPI |
| 62 | +app = FastAPI() |
| 63 | +``` |
| 64 | +Now, we will write the ``GET`` method for the root of the API. As you have already seen, the GET method is ``HTTP request`` method used to fetch data from a source. In web development, it is primarily used to *retrieve data* from server. |
| 65 | + |
| 66 | +The root of the app is ``"/"`` When the API will be called, response will be generated by on this url: ```localhost:8000``` |
| 67 | + |
| 68 | +### GET method |
| 69 | +Following is the code to write GET method which will be calling API. |
| 70 | + |
| 71 | +When the API is called, the ``read_root()`` function will be hit and the JSON response will be returned which will be shown on your web browser. |
| 72 | + |
| 73 | +```python |
| 74 | +@app.get("/") |
| 75 | +def read_root(): |
| 76 | + return {"Hello": "World"} |
| 77 | + |
| 78 | +``` |
| 79 | + |
| 80 | +Tadaaa! you have made your first FastAPI! Now lets run it! |
| 81 | + |
| 82 | +### Running Server and calling API |
| 83 | + |
| 84 | +Open your terminal and give following command: |
| 85 | +```bash |
| 86 | +uvicorn myapi:app --reload |
| 87 | +``` |
| 88 | +Here, ``myapi`` is the name of your API which is name of your python file. ``app`` is the name you have given to your API in assignment ``app = FastAPI()`` |
| 89 | + |
| 90 | +After running this command, uvicorn server will be live and you can access your API. |
| 91 | + |
| 92 | +As right now we have only written root ``GET`` method, only its corresponding response will be displayed. |
| 93 | + |
| 94 | +On running this API, we get the response in JSON form: |
| 95 | + |
| 96 | +```json |
| 97 | +{ |
| 98 | + "Hello": "World" |
| 99 | +} |
| 100 | +``` |
| 101 | +## Path Parameters |
| 102 | +Path parameters are a way to send variables to an API endpoint so that an operation may be perfomed on it. |
| 103 | + |
| 104 | +This feature is particularly useful for defining routes that need to operate on resources identified by unique identifiers, such as user IDs, product IDs, or any other unique value. |
| 105 | + |
| 106 | +### Example |
| 107 | +Lets take an example to make it understandable. |
| 108 | + |
| 109 | + |
| 110 | +Assume that we have some Students 🧑🎓 in our class and we have saved their data in form of dictionary in our API (in practical scenarios they will be saved in a database and API will query database). |
| 111 | +So we have a student dictionary that looks something like this: |
| 112 | + |
| 113 | +```python |
| 114 | +students = { |
| 115 | + 1: { |
| 116 | + "name": "John", |
| 117 | + "age": 17, |
| 118 | + "class": "year 12" |
| 119 | + }, |
| 120 | + 2: { |
| 121 | + "name": "Jane", |
| 122 | + "age": 16, |
| 123 | + "class": "year 11" |
| 124 | + }, |
| 125 | + 3: { |
| 126 | + "name": "Alice", |
| 127 | + "age": 17, |
| 128 | + "class": "year 12" |
| 129 | + } |
| 130 | +} |
| 131 | +``` |
| 132 | +Here, keys are ``student_id``. |
| 133 | + |
| 134 | +Let's say user wants the data of the student whose ID is 2. Here, we will take ID as **path parameter** from the user and return the data of that ID. |
| 135 | + |
| 136 | + |
| 137 | +Lets see how it will be done! |
| 138 | + |
| 139 | +```python |
| 140 | +@app.get("/students/{student_id}") |
| 141 | +def read_student(student_id: int): |
| 142 | + return students[student_id] |
| 143 | +``` |
| 144 | +Here is the explanatory breakdown of the method: |
| 145 | + |
| 146 | +- ``/students`` is the URL of students endpoint in API. |
| 147 | +- ``{student_id}`` is the path parameter, which is a dynamic variable the user will give to fetch the record of a particular student. |
| 148 | +- ``def read_student(student_id: int)`` is the signature of function which takes the student_id we got from path parameter. Its type is defined as ``int`` as our ID will be an integer. |
| 149 | +**Note that there will be automatic type checking of the parameter. If it is not same as type defined in method, an Error response ⛔ will be generated.** |
| 150 | + |
| 151 | +- ``return students[student_id]`` will return the data of required student from dictionary. |
| 152 | + |
| 153 | +When the user passes the URL ``http://127.0.0.1:8000/students/1`` the data of student with student_id=1 is fetched and displayed. |
| 154 | +In this case following output will be displayed: |
| 155 | + |
| 156 | +```json |
| 157 | +{ |
| 158 | + "name": "John", |
| 159 | + "age": 17, |
| 160 | + "class": "year 12" |
| 161 | +} |
| 162 | +``` |
| 163 | + |
| 164 | +## Query Parameters |
| 165 | +Query parameters in FastAPI allow you to pass data to your API endpoints via the URL's query string. This is useful for filtering, searching, and other operations that do not fit well with the path parameters. |
| 166 | + |
| 167 | +Query parameters are specified after the ``?`` symbol in the URL and are typically used for optional parameters. |
| 168 | + |
| 169 | +### Example |
| 170 | +Lets continue the example of students to understand the query parameters. |
| 171 | + |
| 172 | +Assume that we want to search students by name. In this case, we will be sending datat in query parameter which will be read by our method and respective result will be returned. |
| 173 | + |
| 174 | +Lets see the method: |
| 175 | + |
| 176 | +```python |
| 177 | +@app.get("/get-by-name") |
| 178 | +def read_student(name: str): |
| 179 | + for student_id in students: |
| 180 | + if students[student_id]["name"] == name: |
| 181 | + return students[student_id] |
| 182 | + return {"Error": "Student not found"} |
| 183 | +``` |
| 184 | +Here is the explanatory breakdown of this process: |
| 185 | + |
| 186 | +- ``/get-by-name`` is the URL of the endpoint. After this URL, client will enter the query parameter(s). |
| 187 | +- ``http://127.0.0.1:8000/get-by-name?name=Jane`` In this URL, ``name=Jane`` is the query parameter. It means that user needs to search the student whose name is Jane. When you hit this URL, ``read_student(name:str)`` method is called and respective response is returned. |
| 188 | + |
| 189 | +In this case, the output will be: |
| 190 | +```json |
| 191 | +{ |
| 192 | + "name": "Jane", |
| 193 | + "age": 16, |
| 194 | + "class": "year 11" |
| 195 | +} |
| 196 | +``` |
| 197 | +If we pass a name that doesn't exist in dictionary, Error response will be returned. |
| 198 | + |
| 199 | +## POST Method |
| 200 | +The ``POST`` method in FastAPI is used to **create resources** or submit data to an API endpoint. This method typically involves sending data in the request body, which the server processes to create or modify resources. |
| 201 | + |
| 202 | +**⛔ In case of ``GET`` method, sent data is part of URL, but in case of ``POST`` metohod, sent data is part of request body.** |
| 203 | + |
| 204 | +### Example |
| 205 | +Again continuing with the example of student. Now, lets assume we need to add student. Following is the ``POST`` method to do this: |
| 206 | + |
| 207 | +```python |
| 208 | +@app.post("/create-student/{student_id}") |
| 209 | +def create_student(student_id: int, student: dict): |
| 210 | + if student_id in students: |
| 211 | + return {"Error": "Student exists"} |
| 212 | + students[student_id] = student |
| 213 | + return students |
| 214 | +``` |
| 215 | +Here is the explanation of process: |
| 216 | + |
| 217 | +- ``/create-student/{student_id}`` shows that only student_id will be part of URL, rest of the data will be sent in request body. |
| 218 | +- Data in the request body will be in JSON format and will be received in ``student: dict`` |
| 219 | +- Data sent in JSON format is given as: |
| 220 | +```json |
| 221 | +{ |
| 222 | +"name":"Seerat", |
| 223 | +"age":22, |
| 224 | +"class":"8 sem" |
| 225 | + |
| 226 | +} |
| 227 | +``` |
| 228 | +*Note:* I have used Swagger UI to send data in request body to test my ``POST`` method but you may use any other API tesing tool like Postman etc. |
| 229 | + |
| 230 | +- This new student will be added in the dictionary, and if operation is successful, new dictionary will be returned as response. |
| 231 | + |
| 232 | +Following is the output of this ``POST`` method call: |
| 233 | + |
| 234 | +```json |
| 235 | +{ |
| 236 | + "1": { |
| 237 | + "name": "John", |
| 238 | + "age": 17, |
| 239 | + "class": "year 12" |
| 240 | + }, |
| 241 | + "2": { |
| 242 | + "name": "Jane", |
| 243 | + "age": 16, |
| 244 | + "class": "year 11" |
| 245 | + }, |
| 246 | + "3": { |
| 247 | + "name": "Alice", |
| 248 | + "age": 17, |
| 249 | + "class": "year 12" |
| 250 | + }, |
| 251 | + "4": { |
| 252 | + "name": "Seerat", |
| 253 | + "age": 22, |
| 254 | + "class": "8 sem" |
| 255 | + } |
| 256 | +} |
| 257 | +``` |
| 258 | + |
| 259 | +## PUT Method |
| 260 | +The ``PUT`` method in FastAPI is used to **update** existing resources or create resources if they do not already exist. It is one of the standard HTTP methods and is idempotent, meaning that multiple identical requests should have the same effect as a single request. |
| 261 | + |
| 262 | +### Example |
| 263 | +Let's update the record of a student. |
| 264 | + |
| 265 | +```python |
| 266 | +@app.put("/update-student/{student_id}") |
| 267 | +def update_student(student_id: int, student: dict): |
| 268 | + if student_id not in students: |
| 269 | + return {"Error": "Student does not exist"} |
| 270 | + students[student_id] = student |
| 271 | + return students |
| 272 | +``` |
| 273 | +``PUT`` method is nearly same as ``POST`` method but ``PUT`` is indempotent while ``POST`` is not. |
| 274 | + |
| 275 | +The given method will update an existing student record and if student doesnt exist, it'll send error response. |
| 276 | + |
| 277 | +## Additional Content |
| 278 | + |
| 279 | +### Swagger UI |
| 280 | + |
| 281 | +Swagger UI automatically generates UI for API tesing. Just write ``/docs`` with the URL and UI mode of Swagger UI will be launched. |
| 282 | + |
| 283 | +Following Screenshot shows the Swagger UI |
| 284 | + |
| 285 | + |
| 286 | +Here is how I tested ``POST`` method in UI: |
| 287 | + |
| 288 | + |
| 289 | +That's all for FastAPI for now.... Happy Learning! |
0 commit comments