Updated Some Doc
This commit is contained in:
@@ -1,12 +1,19 @@
|
||||
# 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
|
||||
from fastapi import FastAPI
|
||||
@@ -32,59 +39,154 @@ def create_user(name: str, age: int):
|
||||
return {"msg": "User created successfully"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Code Overview
|
||||
|
||||
### POST Endpoint Definition
|
||||
## Explanation
|
||||
|
||||
```python
|
||||
@app.post("/new_user")
|
||||
def create_user(name: str, age: int):
|
||||
```
|
||||
|
||||
* Registers an HTTP **POST** endpoint at `/new_user`
|
||||
* Accepts input parameters:
|
||||
This registers a `POST` endpoint at:
|
||||
|
||||
* `name` → string
|
||||
* `age` → integer
|
||||
* FastAPI automatically validates input types
|
||||
|
||||
---
|
||||
|
||||
### Creating a New Resource
|
||||
|
||||
```python
|
||||
new_user = {"name": name, "age": age}
|
||||
users.append(new_user)
|
||||
```http
|
||||
POST /new_user
|
||||
```
|
||||
|
||||
* Constructs a new user object
|
||||
* Appends it to the in-memory `users` list
|
||||
* Simulates creating a record in a database
|
||||
|
||||
---
|
||||
|
||||
### JSON Response
|
||||
The endpoint receives two parameters:
|
||||
|
||||
```python
|
||||
return {"msg": "User created successfully"}
|
||||
name: str
|
||||
age: int
|
||||
```
|
||||
|
||||
* Returns a structured JSON response
|
||||
* Automatically serialized by FastAPI
|
||||
|
||||
---
|
||||
FastAPI automatically validates the input types. If `age` is not an integer, FastAPI returns a validation error.
|
||||
|
||||
## Example Request
|
||||
|
||||
### Using `curl`
|
||||
|
||||
```bash
|
||||
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
|
||||
{
|
||||
@@ -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
|
||||
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
|
||||
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
|
||||
* 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 `POST` requests when creating new resources.
|
||||
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user