Updated Some Doc
This commit is contained in:
@@ -1,12 +1,19 @@
|
|||||||
# FastAPI – POST Endpoint and JSON Input
|
# FastAPI – POST Endpoint and JSON Input
|
||||||
|
|
||||||
This section demonstrates how to handle **POST requests** in FastAPI to create new resources using request data and return JSON responses.
|
## Overview
|
||||||
|
|
||||||
|
This document explains how to create a `POST` endpoint in FastAPI for adding new users. It covers two approaches:
|
||||||
|
|
||||||
|
1. Sending input as query parameters
|
||||||
|
2. Sending input as a JSON request body using a Pydantic model
|
||||||
|
|
||||||
|
For real API development, the Pydantic model approach is recommended because it provides a cleaner structure, better validation, and more realistic request handling.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Example Application (POST Request)
|
# 1. Example Application Using Query Parameters
|
||||||
|
|
||||||
Extend `main.py` with the following code:
|
Create or update `main.py` with the following code:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
@@ -32,59 +39,154 @@ def create_user(name: str, age: int):
|
|||||||
return {"msg": "User created successfully"}
|
return {"msg": "User created successfully"}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
## Explanation
|
||||||
|
|
||||||
## Code Overview
|
|
||||||
|
|
||||||
### POST Endpoint Definition
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@app.post("/new_user")
|
@app.post("/new_user")
|
||||||
def create_user(name: str, age: int):
|
def create_user(name: str, age: int):
|
||||||
```
|
```
|
||||||
|
|
||||||
* Registers an HTTP **POST** endpoint at `/new_user`
|
This registers a `POST` endpoint at:
|
||||||
* Accepts input parameters:
|
|
||||||
|
|
||||||
* `name` → string
|
```http
|
||||||
* `age` → integer
|
POST /new_user
|
||||||
* FastAPI automatically validates input types
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Creating a New Resource
|
|
||||||
|
|
||||||
```python
|
|
||||||
new_user = {"name": name, "age": age}
|
|
||||||
users.append(new_user)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
* Constructs a new user object
|
The endpoint receives two parameters:
|
||||||
* Appends it to the in-memory `users` list
|
|
||||||
* Simulates creating a record in a database
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### JSON Response
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
return {"msg": "User created successfully"}
|
name: str
|
||||||
|
age: int
|
||||||
```
|
```
|
||||||
|
|
||||||
* Returns a structured JSON response
|
FastAPI automatically validates the input types. If `age` is not an integer, FastAPI returns a validation error.
|
||||||
* Automatically serialized by FastAPI
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Example Request
|
## Example Request
|
||||||
|
|
||||||
### Using `curl`
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -X POST "http://localhost:8000/new_user?name=ali&age=25"
|
curl -X POST "http://localhost:8000/new_user?name=ali&age=25"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Response
|
## Example Response
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"msg": "User created successfully"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Important Note
|
||||||
|
|
||||||
|
In this version, the data is sent through query parameters, not as a JSON body.
|
||||||
|
|
||||||
|
This is acceptable for simple testing, but it is not the best practice for real APIs that create resources.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 2. Recommended Application Using JSON Body
|
||||||
|
|
||||||
|
A better approach is to define a Pydantic model and receive the user data as JSON.
|
||||||
|
|
||||||
|
```python
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
class User(BaseModel):
|
||||||
|
name: str
|
||||||
|
age: int
|
||||||
|
|
||||||
|
|
||||||
|
users = [
|
||||||
|
{"name": "abbas", "age": 20},
|
||||||
|
{"name": "mmd", "age": 37},
|
||||||
|
{"name": "asghar", "age": 19},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/")
|
||||||
|
def home_page():
|
||||||
|
return {"msg": "API is working"}
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/new_user")
|
||||||
|
def create_user(user: User):
|
||||||
|
new_user = {"name": user.name, "age": user.age}
|
||||||
|
users.append(new_user)
|
||||||
|
return {"msg": "User created successfully"}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Explanation
|
||||||
|
|
||||||
|
```python
|
||||||
|
class User(BaseModel):
|
||||||
|
name: str
|
||||||
|
age: int
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates a request model named `User`.
|
||||||
|
|
||||||
|
The model defines the expected structure of the JSON input:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "ali",
|
||||||
|
"age": 25
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
FastAPI uses this model to:
|
||||||
|
|
||||||
|
Validate incoming data
|
||||||
|
Convert JSON into a Python object
|
||||||
|
Generate automatic API documentation
|
||||||
|
Return useful validation errors when input is invalid
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 3. POST Endpoint Definition
|
||||||
|
|
||||||
|
```python
|
||||||
|
@app.post("/new_user")
|
||||||
|
def create_user(user: User):
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates a `POST` endpoint at:
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST /new_user
|
||||||
|
```
|
||||||
|
|
||||||
|
The endpoint expects a JSON request body matching the `User` model.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 4. Creating a New Resource
|
||||||
|
|
||||||
|
```python
|
||||||
|
new_user = {"name": user.name, "age": user.age}
|
||||||
|
users.append(new_user)
|
||||||
|
```
|
||||||
|
|
||||||
|
This code creates a new dictionary using the received request data and appends it to the `users` list.
|
||||||
|
|
||||||
|
The `users` list acts as temporary in-memory storage.
|
||||||
|
|
||||||
|
This simulates inserting a new record into a database.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 5. Returning a JSON Response
|
||||||
|
|
||||||
|
```python
|
||||||
|
return {"msg": "User created successfully"}
|
||||||
|
```
|
||||||
|
|
||||||
|
FastAPI automatically converts the returned dictionary into a JSON response.
|
||||||
|
|
||||||
|
Example response:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -94,34 +196,174 @@ curl -X POST "http://localhost:8000/new_user?name=ali&age=25"
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Verifying the Result
|
# 6. Example Request Using curl
|
||||||
|
|
||||||
After creating a user, retrieve the updated list:
|
```bash
|
||||||
|
curl -X POST "http://localhost:8000/new_user" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"name": "ali", "age": 25}'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Response
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"msg": "User created successfully"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 7. Verifying the Result
|
||||||
|
|
||||||
|
To verify that the user was added, you should also define a `GET /users` endpoint.
|
||||||
|
|
||||||
|
```python
|
||||||
|
@app.get("/users")
|
||||||
|
def get_users():
|
||||||
|
return users
|
||||||
|
```
|
||||||
|
|
||||||
|
Then send this request:
|
||||||
|
|
||||||
```http
|
```http
|
||||||
GET /users
|
GET /users
|
||||||
```
|
```
|
||||||
|
|
||||||
Response will now include the newly added user.
|
Example response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "abbas",
|
||||||
|
"age": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mmd",
|
||||||
|
"age": 37
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "asghar",
|
||||||
|
"age": 19
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ali",
|
||||||
|
"age": 25
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Running the Application
|
# 8. Complete Recommended Version
|
||||||
|
|
||||||
Start the FastAPI service using `uvicorn`:
|
```python
|
||||||
|
from fastapi import FastAPI, status
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
class User(BaseModel):
|
||||||
|
name: str
|
||||||
|
age: int
|
||||||
|
|
||||||
|
|
||||||
|
users = [
|
||||||
|
{"name": "abbas", "age": 20},
|
||||||
|
{"name": "mmd", "age": 37},
|
||||||
|
{"name": "asghar", "age": 19},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/")
|
||||||
|
def home_page():
|
||||||
|
return {"msg": "API is working"}
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/users")
|
||||||
|
def get_users():
|
||||||
|
return users
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/new_user", status_code=status.HTTP_201_CREATED)
|
||||||
|
def create_user(user: User):
|
||||||
|
new_user = {"name": user.name, "age": user.age}
|
||||||
|
users.append(new_user)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"msg": "User created successfully",
|
||||||
|
"user": new_user
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 9. Running the Application
|
||||||
|
|
||||||
|
Start the FastAPI application using `uvicorn`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
uvicorn main:app --reload
|
uvicorn main:app --reload
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The API will run at:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://localhost:8000
|
||||||
|
```
|
||||||
|
|
||||||
|
Interactive API documentation will be available at:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://localhost:8000/docs
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Best Practices
|
# 10. Best Practices
|
||||||
|
|
||||||
* POST requests should be used to create resources
|
Use `POST` requests when creating new resources.
|
||||||
* Avoid modifying in-memory data in production environments
|
|
||||||
* Use request bodies with Pydantic models instead of query parameters for real APIs
|
|
||||||
* Return appropriate HTTP status codes (`201 Created`)
|
|
||||||
* Validate and sanitize all client-provided input
|
|
||||||
* Replace in-memory storage with persistent databases
|
|
||||||
|
|
||||||
|
Use Pydantic models for request bodies instead of query parameters.
|
||||||
|
|
||||||
|
Return proper HTTP status codes, such as:
|
||||||
|
|
||||||
|
```http
|
||||||
|
201 Created
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not use in-memory lists for production data storage.
|
||||||
|
|
||||||
|
Use a real database such as PostgreSQL, MySQL, or MongoDB in production.
|
||||||
|
|
||||||
|
Validate and sanitize all client-provided input.
|
||||||
|
|
||||||
|
Keep model names clear and professional. For example, use `User` instead of `user_class`.
|
||||||
|
|
||||||
|
Return meaningful responses that include the created resource when useful.
|
||||||
|
|
||||||
|
Use `/docs` to test and verify API behavior during development.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 11. Production Note for DevOps
|
||||||
|
|
||||||
|
The in-memory `users` list is reset every time the application restarts. In production environments, application data must be stored in a persistent database.
|
||||||
|
|
||||||
|
For production deployment, the FastAPI application should usually run behind a process manager and reverse proxy, such as:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Gunicorn / Uvicorn workers
|
||||||
|
Nginx or Traefik
|
||||||
|
Docker or Kubernetes
|
||||||
|
PostgreSQL or another persistent database
|
||||||
|
```
|
||||||
|
|
||||||
|
The development command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uvicorn main:app --reload
|
||||||
|
```
|
||||||
|
|
||||||
|
should not be used in production because `--reload` is intended only for local development.
|
||||||
|
|||||||
@@ -1,122 +0,0 @@
|
|||||||
# FastAPI – JSONResponse (Explicit JSON Responses)
|
|
||||||
|
|
||||||
This document demonstrates how to return **explicit JSON responses** in FastAPI using `JSONResponse`.
|
|
||||||
While FastAPI automatically serializes dictionaries to JSON, `JSONResponse` is useful when you need **full control** over the response.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Example Application
|
|
||||||
|
|
||||||
Create or update `main.py` with the following content:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from fastapi import FastAPI, status
|
|
||||||
from fastapi.responses import JSONResponse
|
|
||||||
|
|
||||||
app = FastAPI()
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/")
|
|
||||||
def home():
|
|
||||||
return JSONResponse(
|
|
||||||
content={"msg": "API is working"},
|
|
||||||
status_code=status.HTTP_200_OK
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Why Use `JSONResponse`
|
|
||||||
|
|
||||||
FastAPI automatically converts Python dictionaries into JSON responses.
|
|
||||||
However, `JSONResponse` is useful when you need to:
|
|
||||||
|
|
||||||
* Explicitly control the response type
|
|
||||||
* Set custom status codes dynamically
|
|
||||||
* Customize headers
|
|
||||||
* Return non-standard JSON structures
|
|
||||||
* Override default response behavior
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Response Behavior
|
|
||||||
|
|
||||||
### Endpoint
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /
|
|
||||||
```
|
|
||||||
|
|
||||||
### Response Body
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"msg": "API is working"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTTP Status Code
|
|
||||||
|
|
||||||
```
|
|
||||||
200 OK
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Comparison: Default Response vs JSONResponse
|
|
||||||
|
|
||||||
### Default FastAPI Response
|
|
||||||
|
|
||||||
```python
|
|
||||||
@app.get("/")
|
|
||||||
def home():
|
|
||||||
return {"msg": "API is working"}
|
|
||||||
```
|
|
||||||
|
|
||||||
* Automatically serialized to JSON
|
|
||||||
* Simpler and recommended for most cases
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Explicit JSONResponse
|
|
||||||
|
|
||||||
```python
|
|
||||||
return JSONResponse(
|
|
||||||
content={"msg": "API is working"},
|
|
||||||
status_code=status.HTTP_200_OK
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
* Explicit control over response
|
|
||||||
* Useful for advanced use cases
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## When to Use `JSONResponse`
|
|
||||||
|
|
||||||
* Returning conditional status codes
|
|
||||||
* Adding custom headers
|
|
||||||
* Returning responses outside standard request flow
|
|
||||||
* Building middleware or exception handlers
|
|
||||||
* Integrating with legacy systems
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Running the Application
|
|
||||||
|
|
||||||
Start the application using `uvicorn`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
uvicorn main:app --reload
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Best Practices
|
|
||||||
|
|
||||||
* Prefer returning dictionaries for simple APIs
|
|
||||||
* Use `JSONResponse` only when additional control is required
|
|
||||||
* Keep response formats consistent across endpoints
|
|
||||||
* Avoid mixing response styles unnecessarily
|
|
||||||
* Use response models for structured APIs
|
|
||||||
|
|
||||||
514
Docs/Libs/FastAPI/09-Responces.md
Normal file
514
Docs/Libs/FastAPI/09-Responces.md
Normal file
@@ -0,0 +1,514 @@
|
|||||||
|
# FastAPI – Response Model and JSONResponse
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This document explains two important FastAPI response concepts:
|
||||||
|
|
||||||
|
1. Using `response_model` to control what data is returned to the client
|
||||||
|
2. Using `JSONResponse` when you need explicit control over the response body, status code, or headers
|
||||||
|
|
||||||
|
Response models are especially useful when you want to hide sensitive fields such as passwords from API responses.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 1. Response Model
|
||||||
|
|
||||||
|
## Incorrect Example
|
||||||
|
|
||||||
|
The following code has several issues:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from fastapi import FastAPI, status , HTTPExption
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
class usersin(BaseModel):
|
||||||
|
username: str
|
||||||
|
pass: str
|
||||||
|
|
||||||
|
class usersout(BaseModel):
|
||||||
|
username: str
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/user")
|
||||||
|
def home(user: usersin, responce_model=usersout):
|
||||||
|
return user
|
||||||
|
```
|
||||||
|
|
||||||
|
## Problems in the Code
|
||||||
|
|
||||||
|
### 1. `HTTPExption` is misspelled
|
||||||
|
|
||||||
|
Correct import:
|
||||||
|
|
||||||
|
```python
|
||||||
|
HTTPException
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. `pass` cannot be used as a field name
|
||||||
|
|
||||||
|
`pass` is a reserved keyword in Python.
|
||||||
|
|
||||||
|
Instead of:
|
||||||
|
|
||||||
|
```python
|
||||||
|
pass: str
|
||||||
|
```
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```python
|
||||||
|
password: str
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. `response_model` is written in the wrong place
|
||||||
|
|
||||||
|
This is incorrect:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def home(user: usersin, responce_model=usersout):
|
||||||
|
```
|
||||||
|
|
||||||
|
`response_model` must be passed inside the route decorator.
|
||||||
|
|
||||||
|
Correct:
|
||||||
|
|
||||||
|
```python
|
||||||
|
@app.post("/user", response_model=UserOut)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. `responce_model` is misspelled
|
||||||
|
|
||||||
|
Correct spelling:
|
||||||
|
|
||||||
|
```python
|
||||||
|
response_model
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 2. Correct Response Model Example
|
||||||
|
|
||||||
|
Create or update `main.py` with the following content:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
class UserIn(BaseModel):
|
||||||
|
username: str
|
||||||
|
password: str
|
||||||
|
|
||||||
|
|
||||||
|
class UserOut(BaseModel):
|
||||||
|
username: str
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/user", response_model=UserOut)
|
||||||
|
def create_user(user: UserIn):
|
||||||
|
return user
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 3. How Response Model Works
|
||||||
|
|
||||||
|
## Input Model
|
||||||
|
|
||||||
|
```python
|
||||||
|
class UserIn(BaseModel):
|
||||||
|
username: str
|
||||||
|
password: str
|
||||||
|
```
|
||||||
|
|
||||||
|
This model defines the data that the API receives from the client.
|
||||||
|
|
||||||
|
Example request body:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"username": "abbas",
|
||||||
|
"password": "123456"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The API accepts both fields:
|
||||||
|
|
||||||
|
```text
|
||||||
|
username
|
||||||
|
password
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Output Model
|
||||||
|
|
||||||
|
```python
|
||||||
|
class UserOut(BaseModel):
|
||||||
|
username: str
|
||||||
|
```
|
||||||
|
|
||||||
|
This model defines the data that the API returns to the client.
|
||||||
|
|
||||||
|
Even though the endpoint receives the password, the response only returns the username.
|
||||||
|
|
||||||
|
Example response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"username": "abbas"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The password is removed from the response automatically.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 4. Endpoint Definition
|
||||||
|
|
||||||
|
```python
|
||||||
|
@app.post("/user", response_model=UserOut)
|
||||||
|
def create_user(user: UserIn):
|
||||||
|
return user
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates a `POST` endpoint at:
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST /user
|
||||||
|
```
|
||||||
|
|
||||||
|
The endpoint receives data based on `UserIn` and returns data based on `UserOut`.
|
||||||
|
|
||||||
|
FastAPI uses `response_model` to filter the response before sending it to the client.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 5. Example Request
|
||||||
|
|
||||||
|
## Using curl
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST "http://localhost:8000/user" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"username": "abbas", "password": "123456"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Response
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"username": "abbas"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The password is not included in the response.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 6. Why Use Response Models
|
||||||
|
|
||||||
|
Response models are useful because they help you:
|
||||||
|
|
||||||
|
Protect sensitive data
|
||||||
|
Keep API responses consistent
|
||||||
|
Control exactly what the client receives
|
||||||
|
Improve automatic documentation
|
||||||
|
Validate response data before sending it
|
||||||
|
Separate input schemas from output schemas
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 7. Better Version with Status Code
|
||||||
|
|
||||||
|
For user creation endpoints, it is better to return `201 Created`.
|
||||||
|
|
||||||
|
```python
|
||||||
|
from fastapi import FastAPI, status
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
class UserIn(BaseModel):
|
||||||
|
username: str
|
||||||
|
password: str
|
||||||
|
|
||||||
|
|
||||||
|
class UserOut(BaseModel):
|
||||||
|
username: str
|
||||||
|
|
||||||
|
|
||||||
|
@app.post(
|
||||||
|
"/user",
|
||||||
|
response_model=UserOut,
|
||||||
|
status_code=status.HTTP_201_CREATED
|
||||||
|
)
|
||||||
|
def create_user(user: UserIn):
|
||||||
|
return user
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 8. JSONResponse
|
||||||
|
|
||||||
|
FastAPI automatically converts Python dictionaries into JSON responses.
|
||||||
|
|
||||||
|
For most endpoints, this is enough:
|
||||||
|
|
||||||
|
```python
|
||||||
|
@app.get("/")
|
||||||
|
def home():
|
||||||
|
return {"msg": "API is working"}
|
||||||
|
```
|
||||||
|
|
||||||
|
However, FastAPI also allows you to use `JSONResponse` when you need more control.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 9. Example Application Using JSONResponse
|
||||||
|
|
||||||
|
Create or update `main.py` with the following content:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from fastapi import FastAPI, status
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/")
|
||||||
|
def home():
|
||||||
|
return JSONResponse(
|
||||||
|
content={"msg": "API is working"},
|
||||||
|
status_code=status.HTTP_200_OK
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 10. Response Behavior
|
||||||
|
|
||||||
|
## Endpoint
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /
|
||||||
|
```
|
||||||
|
|
||||||
|
## Response Body
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"msg": "API is working"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## HTTP Status Code
|
||||||
|
|
||||||
|
```http
|
||||||
|
200 OK
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 11. Default Response vs JSONResponse
|
||||||
|
|
||||||
|
## Default FastAPI Response
|
||||||
|
|
||||||
|
```python
|
||||||
|
@app.get("/")
|
||||||
|
def home():
|
||||||
|
return {"msg": "API is working"}
|
||||||
|
```
|
||||||
|
|
||||||
|
This is the recommended style for most simple APIs.
|
||||||
|
|
||||||
|
FastAPI automatically serializes the dictionary into JSON.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Explicit JSONResponse
|
||||||
|
|
||||||
|
```python
|
||||||
|
return JSONResponse(
|
||||||
|
content={"msg": "API is working"},
|
||||||
|
status_code=status.HTTP_200_OK
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
This gives more direct control over the response.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 12. When to Use JSONResponse
|
||||||
|
|
||||||
|
Use `JSONResponse` when you need to:
|
||||||
|
|
||||||
|
Return dynamic status codes
|
||||||
|
Add custom headers
|
||||||
|
Customize the response structure manually
|
||||||
|
Return responses from exception handlers
|
||||||
|
Return responses from middleware
|
||||||
|
Override FastAPI’s default response behavior
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 13. Example: JSONResponse with Custom Status Code
|
||||||
|
|
||||||
|
```python
|
||||||
|
from fastapi import FastAPI, status
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/login")
|
||||||
|
def login():
|
||||||
|
return JSONResponse(
|
||||||
|
content={"msg": "Login successful"},
|
||||||
|
status_code=status.HTTP_200_OK
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 14. Example: JSONResponse with Headers
|
||||||
|
|
||||||
|
```python
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/custom")
|
||||||
|
def custom_response():
|
||||||
|
return JSONResponse(
|
||||||
|
content={"msg": "Custom response"},
|
||||||
|
headers={"X-App-Version": "1.0.0"}
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 15. Complete Example with Response Model and JSONResponse
|
||||||
|
|
||||||
|
```python
|
||||||
|
from fastapi import FastAPI, status
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
class UserIn(BaseModel):
|
||||||
|
username: str
|
||||||
|
password: str
|
||||||
|
|
||||||
|
|
||||||
|
class UserOut(BaseModel):
|
||||||
|
username: str
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/")
|
||||||
|
def home():
|
||||||
|
return JSONResponse(
|
||||||
|
content={"msg": "API is working"},
|
||||||
|
status_code=status.HTTP_200_OK
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.post(
|
||||||
|
"/user",
|
||||||
|
response_model=UserOut,
|
||||||
|
status_code=status.HTTP_201_CREATED
|
||||||
|
)
|
||||||
|
def create_user(user: UserIn):
|
||||||
|
return user
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 16. Running the Application
|
||||||
|
|
||||||
|
Start the FastAPI application using `uvicorn`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uvicorn main:app --reload
|
||||||
|
```
|
||||||
|
|
||||||
|
The API will run at:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://localhost:8000
|
||||||
|
```
|
||||||
|
|
||||||
|
Interactive API documentation will be available at:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://localhost:8000/docs
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 17. Best Practices
|
||||||
|
|
||||||
|
Use `response_model` to control API output.
|
||||||
|
|
||||||
|
Never return sensitive data such as passwords, tokens, or secrets.
|
||||||
|
|
||||||
|
Use separate models for input and output.
|
||||||
|
|
||||||
|
Use clear class names such as `UserIn` and `UserOut`.
|
||||||
|
|
||||||
|
Use `password` instead of `pass` because `pass` is a reserved Python keyword.
|
||||||
|
|
||||||
|
Place `response_model` inside the route decorator, not inside the function parameters.
|
||||||
|
|
||||||
|
Prefer returning normal dictionaries for simple responses.
|
||||||
|
|
||||||
|
Use `JSONResponse` only when extra control is required.
|
||||||
|
|
||||||
|
Use proper HTTP status codes, such as:
|
||||||
|
|
||||||
|
```http
|
||||||
|
200 OK
|
||||||
|
201 Created
|
||||||
|
400 Bad Request
|
||||||
|
401 Unauthorized
|
||||||
|
404 Not Found
|
||||||
|
500 Internal Server Error
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not use `uvicorn --reload` in production.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 18. DevOps Production Note
|
||||||
|
|
||||||
|
In production, the FastAPI application should usually run behind a production-grade ASGI server setup and a reverse proxy.
|
||||||
|
|
||||||
|
A common production stack is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
FastAPI
|
||||||
|
Gunicorn with Uvicorn workers
|
||||||
|
Nginx or Traefik
|
||||||
|
Docker or Kubernetes
|
||||||
|
PostgreSQL or another persistent database
|
||||||
|
```
|
||||||
|
|
||||||
|
The development command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uvicorn main:app --reload
|
||||||
|
```
|
||||||
|
|
||||||
|
is only for local development.
|
||||||
|
|
||||||
|
For production, use a more stable process configuration, such as Gunicorn with Uvicorn workers, container health checks, logging, monitoring, and proper secret management.
|
||||||
Reference in New Issue
Block a user