3.4 Использование шаблонов Jinja и форм в FastAPI
6 из 6 шагов пройдено
1 из 1 баллa  получен

Когда методы API предназначены для обработки веб форм, функции должны получать параметры формы вместо тела запроса, поскольку эти данные формы обычно кодируются как application/x-www-form-urlencoded.

Чтобы использовать формы, сначала установите python-multipart.

pip install python-multipart

Чтобы принять текст записи из формы, мы должны установить Form() к параметру, который мы будем принимать из формы. В нашем случае это сам текст записи. Мы можем настроить Form точно так же, как и  BodyQueryPath, включая параметры валидации, описания и тд. 

from fastapi import FastAPI, status, Body, HTTPException, Request, Form


@app.post("/", status_code=status.HTTP_201_CREATED)
def create_message(request: Request, message: str = Form()) -> HTMLResponse:
    if len(messages_db) == 0:
        max_id_message = 0
    else:
        max_id_message = max([i.dict()['id'] for i in messages_db]) + 1
    messages_db.append(Message(id=max_id_message, text=message))
    return templates.TemplateResponse("message.html", {"request": request, "messages": messages_db})

Обратите внимание, что теперь POST запрос мы будем отправлять на главную страницу нашего приложения, получая сам запрос и текст сообщения из формы. Далее мы добавляем в нашу БД(список) модель Message, заполняя поля id и text, и передаем в шаблон все записи в переменной messages.

Теперь перейдем к написанию самого шаблона message.html, сразу после кода начала блока {% block crud_container %} добавим следующий код:

<section class="container-fluid">
    <form method="post" action="/">
        <div class="col-auto">
            <div class="input-group mb-3">
                <input type="text" name="message" value="{{ text }}" class="form-control"
                       placeholder="Add new message" aria-label="Add message"
                       aria-describedby="button-addon2"/>
                <button class="btn btn-outline-primary" type="submit" id="button-addon2"
                        data-mdb-ripple-color="dark">Add
                </button>
            </div>
        </div>
    </form>
</section>

В итоге наш шаблон будет выглядеть следующим образом:

{% extends "main.html" %}

{% block crud_container %}
<section class="container-fluid">
    <form method="post" action="/">
        <div class="col-auto">
            <div class="input-group mb-3">
                <input type="text" name="message" value="{{ text }}" class="form-control"
                       placeholder="Add new message" aria-label="Add message"
                       aria-describedby="button-addon2"/>
                <button class="btn btn-outline-primary" type="submit" id="button-addon2"
                        data-mdb-ripple-color="dark">Add
                </button>
            </div>
        </div>
    </form>
</section>
{% if message %}
<article class="card container-fluid">
    <br/>
    <h2>ID: {{ message.id }}</h2>
    <p>
        <strong>Text: {{ message.text }}</strong>
    </p>
</article>
{% else %}
<section class="container-fluid">
    <h2>Messages</h2>
    <br>
    <div class="card">
        <ul class="list-group list-group-flush">
            {% for message in messages %}
            <li class="list-group-item">{{ message.id }}. <a href="/message/{{message.id}}">{{ message.text }}</a>
            </li>
            {% endfor %}
        </ul>
    </div>
</section>
{% endif %}
{% endblock %}

Перейдем к тестированию нашего приложения, запустим сервер и перейдем на главную страницу:

Попробуем добавить несколько записей, используя встроенную форму.

Мы видим что наши записи были успешно добавлены, их id был автоматически заполнен. На этом мы закачиваем разработку CRUD проекта. Полный код проекта вы можете посмотреть на GitHub.

В этом разделе мы узнали, что такое шаблоны, основы системы шаблонов Jinja и как использовать их в FastAPI. Мы использовали основы, изученные в первых шагах этого раздела, чтобы решить, какой контент отображать используя синтаксис Jinja. Мы также узнали, что такое наследование шаблонов и как оно работает, на примере шаблона главной страницы.


Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.

Теперь перейдем к написанию самого шаблона messages.html!

@Denis_Romanov, Спасибо, исправил.