В запросе могут передаваться различные данных, например, через отправку каких-то значений в формате json. Рассмотрим, как получать подобные данные.
Для получения данных из тела запроса можно использовать класс Body из пакета fastapi. Данный класс позволяет связать с параметром функции-обработчика запроса либо все тело запроса,
либо какие-то отдельные его значения. Для примера для упрощения отправки данных определим в проекте папку public, в которой создадим новый файл
index.html со следующим кодом:
<!DOCTYPE html>
<html>
<head>
<title>METANIT.COM</title>
<meta charset="utf-8" />
</head>
<body>
<div id="message"></div>
<p>
Введите имя: <br />
<input name="username" id="username" />
</p>
<p>
Введите возраст: <br />
<input name="userage" id="userage" type="number" />
</p>
<button onclick="send()">Отправить</button>
<script>
async function send(){
// получаем введеное в поле имя и возраст
const username = document.getElementById("username").value;
const userage = document.getElementById("userage").value;
// отправляем запрос
const response = await fetch("/hello", {
method: "POST",
headers: { "Accept": "application/json", "Content-Type": "application/json" },
body: JSON.stringify({
name: username,
age: userage
})
});
if (response.ok) {
const data = await response.json();
document.getElementById("message").textContent = data.message;
}
else
console.log(response);
}
</script>
</body>
</html>
В данном случае для ввода данных на веб-странице определено текстовое поле, в которое пользователь вводит свое имя. По нажатию на кнопку срабатывает функция send(),
определенная в коде javascript. Эта функция получает введенное значение и с помощью функции fetch отправляет его по адресу "/hello" в запросе типа POST. При этом в теле запроса посылаются
сериализованные в JSON данные. В частности, посылается объект, в котором свойство name хранит введенное имя.
После отправки запроса мы ожидаем, что сервер в ответ пришлет нам некоторые данные - некоторый объект JSON, в котором будет свойство "message". И значение этого свойства выводим на веб-страницу в элемент с id=message.
Затем определим основной файл приложения main.py, который будет получать и обрабатывать запросы:
from fastapi import FastAPI, Body
from fastapi.responses import FileResponse
app = FastAPI()
@app.get("/")
def root():
return FileResponse("public/index.html")
@app.post("/hello")
#def hello(name = Body(embed=True)):
def hello(data = Body()):
name = data["name"]
age = data["age"]
return {"message": f"{name}, ваш возраст - {age}"}
Здесь при обращении по пути "/" клиенту будет отправляться страница index.html для ввода данных.
Для обработки полученных в POST-запросе данных по адресу "/hello" определена функция hello(). Эта функция имеет один параметр - data, который получает содержимое тела запроса:
data = Body()
То есть здесь data будет представлять весь объект, который отправляется с веб-страницы и который имеет свойства "name" и "age". Этот объект в python будет представлять словарь.
Соответственно, чтобы получить значения свойства "name", обращаемся по одноименному ключу:
name = data["name"]
Подобным образом получаем значение свойства "age". Затем в ответ клиенту посылается словарь с элементом "message".
В примере выше мы получали все данные из тела запроса в один параметр. Однако, установив параметр embed=True, можно получать отдельные значения:
from fastapi import FastAPI, Body
from fastapi.responses import FileResponse
app = FastAPI()
@app.get("/")
def root():
return FileResponse("public/index.html")
@app.post("/hello")
def hello(name = Body(embed=True), age = Body(embed=True)):
return {"message": f"{name}, ваш возраст - {age}"}
Класс Body позволяет валидировать значения из тела запроса. В частности, через конструктор Body можно установить следующие параметры для валидации значений:
min_length: устанавливает минимальное количество символов в значении параметра
max_length: устанавливает максимальное количество символов в значении параметра
pattern: устанавливает регулярное выражение, которому должно соответствовать значение параметра
lt: значение параметра должно быть меньше определенного значения
le: значение параметра должно быть меньше или равно определенному значению
gt: значение параметра должно быть больше определенного значения
ge: значение параметра должно быть больше или равно определенному значению
Применим некотрые параметры:
from fastapi import FastAPI, Body
from fastapi.responses import FileResponse
app = FastAPI()
@app.get("/")
def root():
return FileResponse("public/index.html")
@app.post("/hello")
def hello(name:str = Body(embed=True, min_length=3, max_length=20),
age: int = Body(embed=True, ge=18, lt=111)):
return {"message": f"{name}, ваш возраст - {age}"}
В данном случае значение параметра name должно иметь не меньше 3 и не больше 20 символов, а параметр "age" должен представлять число в диапазоне от 18 (включительно) до 111 (не включая)