DevGang
Авторизоваться

Как настроить REST API во Flask за 5 шагов 

Существует множество способов создания REST API, наиболее распространенным из которых является приложение Django с DRF. Другие люди пробуют FastAPI.

Но если вы используете приложение на основе Flask, я недавно попробовал библиотеку Flask-RESTX, которая включает в себя несколько замечательных функций:

  1. Документация Swagger (черт возьми, да!)
  2. Маршаллинг ответа
  3. Cинтаксический анализ запросов
  4. Обработка ошибок, ведение журнала и поддержка blueprint. Аккуратная интеграция с Flask.

В этой демонстрации я покажу вам, как настроить быстрый REST API с документацией Swagger, синтаксическим анализом запросов и простым форматированием ответа.

Начнем с инициализации blueprint и определения объекта api в новом модуле. Я назвал это как api.py.

blueprint = Blueprint("api", __name__, url_prefix="/api/v1")

api = Api(
    blueprint,
    version="1.0",
    title="Mini REST API",
    description="A mini REST API",
)
ns = api.namespace("items", description="Item operations")
api.add_namespace(ns)

Flask-RESTX поддерживает Flask Blueprint, и их очень просто реализовать.

Мое приложение обслуживается по http://localhost:5000, но мой базовый URL-адрес API будет http://localhost:5000/api/v1. На этой же странице вы можете найти документацию Swagger.

Далее напишем базовые модели. Мой пример API будет управлять объектами Items и Details, поэтому мне нужно написать модели, которые будут отвечать за их представление в стандартном ответе API.

detail_model = api.model("Detail", {"id": fields.Integer, "name": fields.String})
item_model = api.model(
    "Item",
    {
        "id": fields.Integer,
        "name": fields.String,
        "details": fields.List(fields.Nested(detail_model)),
    },
)

Идея написания моделей заключается в использовании маршалинга ответов Flask-RESTX, поэтому независимо от того, масштабируются ли наши объекты, ответ всегда будет таким, каким мы его документируем в наших моделях. Flask-RESTX включает в себя множество инструментов для этого, таких как переименование атрибутов, сложных, настраиваемых и вложенных полей и т.д.

Последний шаг настройки - написание парсера запроса.

item_parser = api.parser()
item_parser.add_argument("id", type=int, location="form")
item_parser.add_argument("name", type=str, location="form")

detail_parser = api.parser()
detail_parser.add_argument("id", type=int, location="form")
detail_parser.add_argument("name", type=str, location="form")

Таким же образом, как и раньше, мы используем синтаксический анализатор запросов Flask-RESTX для чтения и проверки значений, которые мы ожидаем получить в наших конечных точках. В этом случае я планирую реализовать два объектных API, которые будут добавлять элементы к нашим объектам базы данных. (Наша база данных - это простой объект в памяти 😅)

memory_object = [
    {
        "id": 1,
        "name": "Item 1",
        "details": [
            {"id": 1, "name": "Detail 1"},
            {"id": 2, "name": "Detail 2"},
        ],
    }
]

Пришло время реализовать наши API. Первый API, который я хочу создать, - это тот, который управляет элементами. Я назову это ItemApi, и маршрут будет /, что означает корень пространства имен items.

@ns.route("/")
class ItemsApi(Resource):
    """
    API for handling the Item list resource
    """

    @api.response(HTTPStatus.OK.value, "Get the item list")
    @api.marshal_list_with(item_model)
    def get(self) -> list[Item]:
        """
        Returns the memory object
        """
        return memory_object

    @api.response(HTTPStatus.OK.value, "Object added")
    @api.expect(item_parser)
    def post(self) -> None:
        """
        Simple append something to the memory object
        """
        args = item_parser.parse_args()
        memory_object.append(args)

Это активирует две конечные точки:

  • GET /api/v1/items/ - Список item_model 
  • POST /api/v1/items/ - Создание item_parser

Все декораторы предоставляются Flask-RESTX. Класс HTTPStatus предоставляется модулем http. Довольно просто, а?

Этот класс будет управлять одним ресурсом элемента. Итак, чтобы получить его данные и добавить детали, нам понадобится следующая реализация:

@ns.route("/<int:item_id>")
class ItemApi(Resource):
    """
    API for handling the single Item resource
    """

    @api.response(HTTPStatus.OK.value, "Get the item list")
    @api.response(HTTPStatus.BAD_REQUEST.value, "Item not found")
    @api.marshal_with(item_model)
    def get(self, item_id: int) -> Item:
        """
        Returns the memory object
        """
        try:
            return self._lookup(item_id)
        except StopIteration:
            return api.abort(HTTPStatus.BAD_REQUEST.value, "Item not found")

    def _lookup(self, item_id):
        return next(
            (item for item in memory_object if item["id"] == item_id),
        )

    @api.response(HTTPStatus.NO_CONTENT.value, "Object added")
    @api.response(HTTPStatus.BAD_REQUEST.value, "Item not found")
    @api.expect(detail_parser)
    def post(self, item_id: int) -> None:
        """
        Simple append details to the memory object
        """
        args = item_parser.parse_args()
        try:
            if item := self._lookup(item_id):
                item["details"].append(args)
            return None
        except StopIteration:
            return api.abort(HTTPStatus.BAD_REQUEST.value, "Item not found")

Это позволит включить еще две конечные точки:

  • GET /api/v1/items/<item_id> - Eдиный ресурс item_model
  • POST /api/v1/items/<item_id> - Создание detail_parser

Чтобы завершить наше приложение, вам нужно только импортировать модуль app.py и зарегистрировать Blueprint.

from api import blueprint

app = Flask(__name__)  # This line already exists
app.register_blueprint(blueprint)
#Python
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

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

Попробовать

В подарок 100$ на счет при регистрации

Получить