image_pdf

Содержание

Все, кто писал web‑приложения, наверняка знают, как сделать HTTP‑запрос на сервер (программное обеспечение), получить от него данные и заполнить ими изменяемую часть своей страницы в браузере.

Цель этой статьи — показать, как применить Python 3, Flask и Connexion для создания полезного API REST, который может проверять ввод/вывод. В качестве бонуса — ссылка на документацию Swagger. Кроме того, мы создадим простое, но полезное одностраничное web‑приложение, которое продемонстрирует возможности API с JavaScript при обновлении Document Object Model — DOM.

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

Данные можно хранить в базе данных, в файле или получить к ним доступ через некоторый сетевой протокол. Однако, наши данные мы будет просто хранить в оперативной памяти, т.е. при завершении работы приложения они исчезнут. Одно из назначений API — скрытие деталей реализации структуры данных и отделение их от приложения.

Что есть REST

Прежде чем вы начнете создавать сервер API, я хочу немного поговорить о REST. Есть масса информации о REST, которую несложно найти в Yandex и Google, а я не хочу здесь повторяться.

Я просто хочу поделиться своим взглядом на REST и возможностями построения API. К REST я отношусь, как к набору соглашений, использующих свойства протокола HTTP для обеспечения операций CRUD (Create, Read, Update и Delete или Создание, Чтение, Обновление и Удаление, если по русски) для элементов и коллекций этих элементов. CRUD хорошо сочетается с названиями методов HTTP‑протокола:

Операция
HTTP метод
Описание
Create
POST
Создание новой, уникальной сущности
Read
GET
Чтение информации о сущности или коллекции сущностей
Update
PUT
Обновить информацию о сущности
Delete
DELETE
Удалить сущность

Эти операции можно выполнять, как над сущностями, так и над любыми другими ресурсами. Полезно думать о ресурсе как о чем-то, что можно определить как существительное: человек, заказ чего‑либо, адрес человека. Такая мысль о ресурсе очень естественно приводит к URL‑адресу (Unique Resource Locator — уникальный указатель ресурса).

URL идентифицирует уникальный ресурс в сети, который будет работать с одним и тем же снова и снова, используя один и тот же URL. Благодаря этим двум идеям у нас есть возможность наполнить функционалом своё приложение для какой‑то уникальной сущности, идентифицируемой в Интернете. Это очень конструктивный и полезный подход.

Такая идея имеет огромное значение при создании чистых API и выполнения действий, которые требуются многим приложениям с API.

Что не есть REST

Хотя REST полезен и помогает определять API для взаимодействия через веб‑интерфейс, иногда его используют не по назначению. Существует масса случаев, когда необходимо сделать какую-то работу или действие напрямую. Примером может служить подстановка строк и, естественно, создавать для этого API глупость. Пока именно это и обсудим. Вот URL, который надо создать:

/api/substituteString?string=&search_string=&sub_string=

Здесь string — строка, где надо что‑то заменить, search_string — подстрока для замены, а sub_string — то, на что надо заменить search_string. Безусловно, это можно связать с некоторым кодом на сервере, который и выполняет эту работу. Но, зная что такое REST, мы понимаем — здесь есть проблемы.

Первое, что приходит на ум — подобный URL не указывает на уникальный ресурс, а то, что он возвращает, полностью зависит от переменной части пути. Кроме того, для такого URL нет никакого CRUD. В действительности здесь нужен только один метод HTTP, но имя метода ничего не говорит о действии, которое нужно выполнить.

Как API, это тоже не здорово. Значение переменных пути зависит от их места в URL. Эту проблему можно решить, изменив URL‑адрес и вместо него использовать строку запроса, например:

/api/substituteString?string=<string>&search_string=<search_string>&sub_string=<sub_string>

Часть URL /api/substituteString вообще не является объектом (существительным) или некоторым набором элементов: это действие (глагол) и не вписывается в соглашения REST. Попытка заставить его это сделать приведёт к плохому API. То, о чём здесь шёл разговор, на самом деле, представляет собой Remote Procedure Call или удаленный вызов процедур (RPC). Думать об всём этом как о RPC гораздо более мудро.

Прелесть заключается в том, что REST и RPC в API могут прекрасно сосуществовать без каких-либо проблем! Принимая во внимание возможности каждого из них, в своем дизайне API вы можете одновременно использовать и то и другое, дополняя друг друга. Есть множество ситуаций, когда было бы полезно выполнять CRUD‑операции над чем-либо, есть также множество ситуаций, когда было бы полезно выполнить действие с существующим объектом (как параметром), не изменяя сам объект.

API REST для People

В нашем примере программы вы создадите API REST, обеспечивающий доступ к группе людей, из таблицы People, с возможность выполнять CRUD‑операции с отдельными записями этой коллекции. Вот дизайн API для нашей коллекции People:

Действие
HTTP метод
URL Path
Описание
Create
POST
/api/people
Определение уникального URL для создание новой персоны
Read
GET
/api/people/Farrell
Определение уникального URL для чтения информации об отдельной персоне в коллекции персон
Delete
DELETE
/api/orders/Farrell
Определение уникального URL для удаления выбранной персоны

Быстрый старт

В первую очередь, используя микро‑фреймворк Flask, создадим простой web‑сервер. Для начала создайте каталог, где будут храниться файлы с кодами. Кроме того, вспомните, что работать следует в виртуальной среде (virtualenv), потому как позже нам необходимо установить модули, которые понадобятся в работе. Опять-же, создайте каталог templates для шаблонов.

Приведенный ниже код на Python запускает очень простой веб‑сервер, который при обращении к домашней странице отвечает сообщением Hello World:

from flask import (
    Flask,
    render_template
)

# Создадим экземпляр приложения
app = Flask(__name__, template_folder="templates")

# Создадим маршрут URL в своём приложении для "/"
@app.route('/')
def home():
    """
    Эта функция просто отвечает на URL "localhost:5000/" в 
    адресной строке браузера

    :return:        представленный шаблон 'home.html'
    """
    return render_template('home.html')

# Если мы работаем в автономном режиме, запустим приложение
if __name__ == '__main__':
    app.run(debug=True)

Кроме того, в папке шаблонов templates следует создать файл home.html, поскольку именно от будет отображаться в браузере при переходе по URL '/'. Вот содержимое файла home.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Application Home Page</title>
</head>
<body>
    <h2>
        Hello World!
    </h2>
</body>
</html>

Заметили, что основной файл HTML называется home.html, а не index.html. Это сделано преднамеренно, поскольку после импорта модуля Connexion наличие файла index.html в каталоге шаблонов вызывает проблемы.

Вы можете запустить приложение из командной строки из каталога с активным Python VirtualEnv, содержащего файл server.py:

python server.py

При загрузке этого приложение, запускается web‑сервер с портом 5000, который для Flesk является портом по умолчанию. Если вы откроете браузер и перейдете по адресу localhost:5000, то должны увидеть Hello World!. Прямо сейчас полезно увидеть, что web‑сервер работает. Позже вы измените файл home.html до полностраничного web‑приложения с использованием разработанного API REST.

В своей программе на Python вы импортировали модуль Flask, обеспечивая своему приложению функциональность Flask. Затем вы создали экземпляр приложения Flask, переменную app. Затем вы подключили URL‑маршрут '/' к функции home() с помощью декоратора, определенного как @app.route('/'). Эта функция вызывает функцию Flask render_template() для поиска файла home.html в каталоге шаблонов и передаче его в браузер.

Весь пример кода доступен по ссылке, приведенной в конце этой статьи.

Connexion для добавления конечной точки API REST

Теперь, когда у вас есть работающий web‑сервер, давайте добавим конечную точку API REST. Для этого будем использовать модуль Connexion, который устанавливается с помощью pip:

$ pip install connexion

Теперь модуль Connexion доступен в вашей программе. Connexion позволяет Python-программе использовать спецификации Swagger, что обеспечивает множество функциональных возможностей: проверка входных и выходных данных вашего API, простой способ настройки URL‑адресов и ожидаемых параметров конечных точек API, а также действительно приятный пользовательский интерфейс для работы и изучения созданного API.

Все это определяется файлом конфигурации, к которому может обращаться ваше приложение. На сайте Swagger даже есть конфигуратор для онлайн-редактирования, который помогает создавать и/или проверять синтаксис файла конфигурации, который вы создаёте.

Добавление Connexion на сервер

Добавление URL‑адреса конечной точки API REST в приложение с помощью Connexion состоит из двух частей. Вы добавите Connexion на сервер и создадите файл конфигурации, который он будет использовать. Для добавления Connexion на сервер измените ваш скрипт на Python:

from flask import render_template
import connexion

# Создадим экземпляр приложения
app = connexion.App(__name__, specification_dir='./')

# Прочитаем файл swagger.yml для настройки конечных точек
app.add_api('swagger.yml')

# Создадим маршрут URL в нашем приложении для "/"
@app.route('/')
def home():
    """
    Эта функция просто отвечает на URL "localhost:5000/" в браузера
    
    :return:        подствляет шаблон 'home.html'
    """
    return render_template('home.html')

# Если мы работаем в автономном режиме, запускаем приложение
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

Для подключения Connexion на сервере вы сделали несколько изменений. Оператор import connexion добавляет модуль в программу. Следующим шагом является создание экземпляра приложения с использованием Connexion, а не Flask. Приложение Flask обязательно создается, но теперь к нему добавлены дополнительные функции.

При создании экземпляра приложения определён параметр spec_dir, который сообщает Connexion, каталог файла конфигурации. В нашем случае это текущий каталог. Сразу после этого вы добавили строку: app.add_api('swagger.yml')

Экземпляр приложения должен прочитать файл swagger.yml из указанного каталога и настроить систему для обеспечения функциональности Connexion.

Конфигурационный файл Swagger

Файл swagger.yml представляет собой файл YAML или JSON, содержащий всю информацию, необходимую для настройки сервера на проверку входных параметров и проверку выходных данных для ответа, определения URL‑адреса конечной точки и пользовательский интерфейс Swagger. Вот файл swagger.yml, определяющий конечную точку GET/api/people, которую предоставит ваш API REST:

swagger: "2.0"
info:
  description: This is the swagger file that goes with our server code
  version: "1.0.0"
  title: Swagger REST Article
consumes:
  - "application/json"
produces:
  - "application/json"

basePath: "/api"

# Пути, поддерживаемые приложением сервера
paths:
  /people:
    get:
      operationId: "people.read"
      tags:
        - "People"
      summary: "The people data structure supported by the server application"
      description: "Read the list of people"
      responses:
        200:
          description: "Successful read people list operation"
          schema:
            type: "array"
            items:
              properties:
                fname:
                  type: "string"
                lname:
                  type: "string"
                timestamp:
                  type: "string"

Этот файл организован иерархически: уровни отступов представляют уровень владения или область действия.

Например, paths определяет начало, где определены все URL конечных точек API. Значение /people с отступом, определяющее уровень описания всех URL конечных точек /api/people. Элемент get: с отступом, определяющий раздел определений, связанных с запросом HTTP GET к конечной точке URL /api/people. И так продолжается на протяжении всей конфигурации.

Вот значения полей в этом разделе файла swagger.yml:

Этот раздел содержит часть информации о глобальной конфигурации:

  1. swagger: сообщает Connexion о версии Swagger API.
  2. info: начинает новый «раздел» информации о создаваемом API.
  3. description: описание того, что собой представляет API и для чего он сделан в системе пользовательского интерфейса Connexion.
  4. version: номер пользовательской версии API
  5. title: пользовательский заголовок в системе пользовательского интерфейса Connexion
  6. consumes: сообщает Connexion об ожидаемом MIME-типе API.
  7. produces: сообщает Connexion о типе ожидаемого с вызывающей стороны API контента.
  8. basePath: "/api" определяет корень API в качестве пространства имен, из которого будет получен API REST.

В этом разделе начинается настройка путей URL‑адресов конечных точек API:

  1. paths: определяет раздел конфигурации, содержащий все конечные точки API REST.
  2. /people: определяет один URL вашей конечной точки.
  3. get: определяет метод HTTP, на который будет отвечать URL конечной точки. Вместе с предыдущими определениями создается URL‑адрес конечной точки GET/api/people.

В этом разделе начинается настройка одного URL конечной точки /api/people:

  1. operationId: "people.read" определяет путь/функцию импорта Python, которая будет отвечать на запрос HTTP GET/api/people. "people.read" часть может идти так глубоко, как вам нужно для того, чтобы подключить функцию к HTTP-запросу. Что-то вроде "<package_name>.<package_name>.<package_name>.<function_name>" будет работать так же хорошо. Вы сделаете это в ближайшее время.
  2. tags: группировка пользовательского интерфейса. Все методы CRUD, которые вы определите для конечной точки пользователей, будут использовать тег этого определения.
  3. summary определяет отображаемый текст интерфейса пользователя для этой конечной точки.
  4. description: определяет, что интерфейс UI будет отображать для заметок о реализации.

Этот раздел определяет раздел конфигурации успешного ответа от конечной точки URL:

  1. response: начало раздела ожидаемого ответа.
  2. 200: раздел для успешного ответа, код состояния HTTP 200.
  3. description: отображаемый текст интерфейса для ответа 200.
  4. schema: ответ как схема или структура.
  5. type: структура схемы в виде массива.
  6. items: начало определения элементов в массиве.
  7. properties: элементы в массиве как объекты, имеющие пары ключ/значение.
  8. fname: первый ключ объекта.
  9. type: строка значения, ассоциированного с fname.
  10. lname: второй ключ объекта.
  11. type: строка значения, ассоциированного с lname.
  12. timestamp: третий ключ объекта.
  13. type: строка значения, ассоциированного с timestamp.

Обработчик конечной точки для People

В файле swagger.yml вы настроили Connexion со значением operationId для вызова модуля people и read, функция внутри модуля для обработки HTTP‑запроса GET/api/people. Это означает, что модуль people.py должен существовать и содержать функцию read(). Вот модуль people.py, который вы создадите:

from datetime import datetime

def get_timestamp():
    return datetime.now().strftime(("%Y-%m-%d %H:%M:%S"))

# Data to serve with our API
PEOPLE = {
    "Farrell": {
        "fname": "Doug",
        "lname": "Farrell",
        "timestamp": get_timestamp()
    },
    "Brockman": {
        "fname": "Kent",
        "lname": "Brockman",
        "timestamp": get_timestamp()
    },
    "Easter": {
        "fname": "Bunny",
        "lname": "Easter",
        "timestamp": get_timestamp()
    }
}

# Create a handler for our read (GET) people
def read():
    """
    Эта функция отвечает на запрос для /api/people
    с полными списками людей

    :return:        отсортированный список людей
    """
    # Создать список людей из наших данных
    return [PEOPLE[key] for key in sorted(PEOPLE.keys())]

Далее вы создали вспомогательную функцию с именем get_timestamp(), которая генерирует строковое представление текущей временной отметки. Используется для создания структуры в памяти и изменения данных, когда вы начинаете изменять их с помощью API.

Затем вы создали структуру данных словаря PEOPLE, которая представляет собой базу данных простых имен с указанием фамилии. Это переменная модуля, поэтому ее состояние сохраняется между вызовами API REST. В реальном приложении данные PEOPLE будут существовать в базе данных, файле или на сетевом ресурсе, что сохранит данные после запуска/остановки веб‑приложения.

Затем вы создали функцию read(). Она вызывается, когда сервер получает HTTP-запрос GET/api/people. Возвращаемое значение этой функции преобразуется в строку JSON (напомним, определение produces: в файл swagger.yml). Созданная вами функция read() создает и возвращает список людей, отсортированных по фамилии.

Выполнение кода вашего сервера и переход в браузере по адресу localhost: 5000/api/people отобразит список людей на экране:

[
  {
    "fname": "Kent",
    "lname": "Brockman",
    "timestamp": "2018-05-10 18:12:42"
  },
  {
    "fname": "Bunny",
    "lname": "Easter",
    "timestamp": "2018-05-10 18:12:42"
  },
  {
    "fname": "Doug",
    "lname": "Farrell",
    "timestamp": "2018-05-10 18:12:42"
  }
]

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

Пользовательский интерфейс Swagger

Теперь у вас есть простой веб-API, работающий с конечной точкой одного URL. На этом этапе было бы разумно подумать: «Настрока с помощью файла swagger.yml это круто и все же, что мне это дало?»

Вы были бы правы, когда так задумались. Мы не воспользовались проверкой ввода или вывода. Все, что swagger.yml дало нам, было определением пути для кода, связанного с URL конечной точки. Однако за дополнительную работу вы получаете также создание Swagger UI для вашего API.

Если вы перейдете к localhost: 5000/api/ui, система откроет страницу, которая выглядит примерно так:

Пользовательский интерфейс Swagger
Пользовательский интерфейс Swagger

Это начальный интерфейс Swagger и показывает список URL конечных точек, поддерживаемых в нашей конечной точке localhost: 5000/api. Он создается автоматически Connexion при анализе файла swagger.yml.

Если вы щелкнете по конечной точке /people в интерфейсе, то получите гораздо больше информации о своём API, которая должна выглядеть примерно так:

Информация о конечной точке RESR API
Информация о конечной точке RESR API

Здесь отображается структура ожидаемого ответа, content-type ответа и текст описания, который вы ввели для конечной точки в файле swagger.yml.

Вы даже можете попробовать конечную точку, нажав кнопку Try It Out! в нижней части экрана. Это еще больше расширит интерфейс, что выглядит примерно так:

Проверка конечной точки
Проверка конечной точки

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

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

Кроме того, конфигурация предлагает хороший, чистый, способ продумать и создать URL конечных точкек API. Из своего опыта я знаю, что с течением времени API могут развиваться, иногда, случайным образом, что, в лучшем случае, затрудняет поиск кода, поддерживающего конечные точки и их координацию.

Отделяя код конфигурации для URL-адреса конечной точки API, мы отделяем одно от другого. Это само по себе очень полезно для моей системы построения API, поддерживающей одностраничные веб-приложения.

Создание полного API

Нашей первоначальной целью было создание API, обеспечивающего полный CRUD-доступ к структуре наших сотрудников. Как вы помните, определение нашего API выглядит так:

Действие
HTTP метод
URL Path
Описание
Create
POST
/api/people
Определение уникального URL для создание новой персоны
Read
GET
/api/people/Farrell
Определение уникального URL для чтения информации об отдельной персоне в коллекции персон
Update
PUT
/api/people/Farrell
Определение уникального URL для обновления выбранной персоны
Delete
DELETE
/api/orders/Farrell
Определение уникального URL для удаления выбранной персоны

Для этого вы расширите файлы swagger.yml и people.py для поддержки полного API, определенного выше. Для краткости будет предоставлена только ссылка на оба файлов :

Полный пользовательский интерфейс Swagger

После того как вы обновили файлы swagger.yml и people.py для завершения функциональности API людей, система пользовательского интерфейса Swagger обновится соответствующим образом и будет выглядеть примерно так:

Полный API REST в интерфейсу Swagger
Полный API REST в интерфейсу Swagger

Этот пользовательский интерфейс позволяет просматривать всю документацию, включенную в файл swagger.yml и взаимодействовать со всеми URL-адресами конечных точек, составляющими функциональность CRUD интерфейса людей.

Демонстрация одностраничного приложения

У вас есть работающий API REST с отличной системой документирования и взаимодействия с интерфейсом Swagger. Но что нам с этим делать? Следующим шагом является создание веб-приложения, демонстрирующего использование API в полупрактической форме.

Вы создадите веб-приложение, которое отображает людей на экране, а также позволяет пользователю создавать новых людей, обновлять существующих людей и удалять людей. Все это будет обрабатываться вызовами AJAX из JavaScript по URL-адресам конечных точек API пользователей.

Для начала вам нужно расширить файл home.html таким образом:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Application Home Page</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css">
    <link rel="stylesheet" href="static/css/home.css">
    <script
      src="http://code.jquery.com/jquery-3.3.1.min.js"
      integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
      crossorigin="anonymous">
    </script>
</head>
<body>
    <div class="container">
        <h1 class="banner">People Demo Application</h1>
        <div class="section editor">
            <label for="fname">First Name
                <input id="fname" type="text" />
            </label>
            <br />
            <label for="lname">Last Name
                <input id="lname" type="text" />
            </label>
            <br />
            <button id="create">Create</button>
            <button id="update">Update</button>
            <button id="delete">Delete</button>
            <button id="reset">Reset</button>
        </div>
        <div class="people">
            <table>
                <caption>People</caption>
                <thead>
                    <tr>
                        <th>First Name</th>
                        <th>Last Name</th>
                        <th>Update Time</th>
                    </tr>
                </thead>
                <tbody>
                </tbody>
            </table>
        </div>
        <div class="error">
        </div>
    </div>
</body>
<script src="static/js/home.js"></script>
</html>

Приведенный выше HTML-код расширяет файл home.html для получения внешнего CSS файла normalize.min, который сбрасывает CSS для нормализации форматирования элементов в разных браузерах.

Он также получает внешний файл jquery-3.3.1.min.js для обеспечить функциональности jQuery, которую вам придётся использовать для создания интерактивности приложения на одностраниснике.

Приведенный выше HTML-код создает статическую структуру приложения. Динамические части, появляющиеся в структуре таблицы, будут добавляться JavaScript во время загрузки и при взаимодействии пользователя с приложением.

Статические файлы

В созданном вами файле home.html есть ссылки на два статических файла: static/css/home.css и static/js/home.js. Чтобы их добавить,неоходимо сформировать следующую структуру каталогов приложения:

static/
│
├── css/
│   └── home.css
│
└── js/
    └── home.js

Поскольку каталог с именем static будет автоматически обслуживаться приложением Flask, любые файлы, которые вы поместите в папки css и js, будут доступны для Файл home.html. Для краткости, вот ссылки на эти файлы home.css и home.js:

Файл JavaScript

Как уже упоминалось, файл JavaScript обеспечивает все взаимодействие с веб-приложением и его обновление. Это достигается разделением необходимой функциональности на три части с помощью дизайна шаблона MVC (Модель/Вид/Контроллер).

Каждый объект создается с помощью функции, вызывающей себя, возвращающей свой собственный API для использования другими компонентами. Например, Контроллеру передаются экземпляры Модели и Представления как параметры в его экземпляре. Он взаимодействует с этими объектами через открытые методы API.

Единственное другое соединение между Моделью и Контроллером осуществляется посредством пользовательских событий в вызовах метода AJAX:

  1. Model обеспечивает связь с API людей. Его собственный API — это то, что Контроллер вызывает для взаимодействия с сервером, когда этого требует событие взаимодействия с пользователем.
  2. View предоставляет механизм обновления веб-приложения DOM. Его собственный API — это то, что Контроллер вызывает для обновления DOM, когда этого требует событие взаимодействия с пользователем.
  3. Controller предоставляет все обработчики событий для взаимодействия пользователя с веб-приложением. Это позволяет ему выполнять вызовы в Модель для отправки запросов в API людей и в представление для обновления DOM новой информацией, получаемой из API людей.

Он также обрабатывает пользовательские события, сгенерированные асинхронными запросами AJAX, сделанными Моделью в API людей.

Вот схема структуры MVC, используемой в файле home.js:

Шаблон MVC
Шаблон MVC

Идея заключается в том, что контроллер имеет сильную связь как с моделью, так и с представлением. Модель имеет слабую связь (пользовательские события) с контроллером и вообще не связана с представлением. Слабая связь между моделью и контроллером снижает связь и зависимость, что в нашем случае очень полезно.

Demo приложение

После создания веб-приложение в браузере оно будет выглядеть следующим образом:

Наше Demo приложение
Наше Demo приложение

Кнопка Create позволяет пользователю создать нового человека в структуре людей на сервере. Когда вы вводите Имя и Фамилию и нажимаете Создать, Контроллер вызывает Модель, чтобы сделать запрос к конечной точке URL POST/api/people. Это подтвердит, что фамилия еще не существует. Если этого не произойдет, это создаст нового человека в структуре людей.

Это генерирует пользовательское событие в модели, которое заставляет контроллер снова вызвать модель для запроса GET/api/people, который вернет полный список отсортированных людей. Контроллер затем передает это в представление, чтобы перерисовать таблицу людей.

Двойной щелчок по любой строке таблицы заполняет поля «Имя» и «Фамилия» в разделе редактора приложения. На этом этапе пользователь может либо обновить, либо удалить человека.

Для успешного обновления пользователь должен что-то изменить в имени. Фамилия должна оставаться такой же, как и ключ поиска для человека, которого нужно обновить. При нажатии кнопки «Обновление» контроллер вызывает модель, чтобы отправить запрос к конечной точке URL-адреса PUT/api/people/{lname}. Это проверит, что Фамилия в настоящее время существует. Если это так, это обновит этого человека в структуре людей.

Это генерирует пользовательское событие в модели, которое заставляет контроллер снова вызвать модель для запроса GET/api/people, который вернет полный список отсортированных людей. Контроллер затем передает это в представление, чтобы перерисовать таблицу людей.

Для успешного удаления пользователю достаточно нажать Delete. При нажатии Delete Контроллер вызывает Модель, чтобы сделать запрос к конечной точке URL DELETE/api/people /{lname}. Это проверит, что фамилия в настоящее время существует. Если это так, он удалит этого человека из структуры людей.

Это генерирует пользовательское событие в модели, которое заставляет контроллер снова вызвать модель для запроса GET/api/people, который вернет полный список отсортированных людей. Контроллер затем передает это в представление, чтобы перерисовать таблицу людей.

Попробуйте сделать преднамеренные ошибки в редакторе, такие как неправильное написание фамилии, и посмотрите ошибки, сгенерированные API, представленными в веб-приложении.

Пример кода

Полный пример кода для этой статьи доступен здесь. Существует четыре версии кода, каждая из которых находится в каталоге version_#, где # варьируется от 1 до 4. Четыре версии соответствуют четырём разделам статьи:

  1. version_1: содержит начальный web‑сервер, который обслуживает home.html file.
  2. version_2: содержит web‑сервер с добавленным Connexion и конечную точку URL‑адреса API первых людей.
  3. version_3: содержит завершенный API пользователей со всеми поддерживаемыми URL конечных точек.
  4. version_4: содержит готовый API и одностраничное web‑приложение для его демонстрации.

Заключение

В этом уроке вы увидели, как относительно просто создать всеобъемлющий API REST с помощью Python. С модулем Connexion и некоторыми дополнительными настройками можно создать полезную документацию и интерактивную систему, где ваш API гораздо более приятен для пользователей для понимания и взаимодействия.

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

Оригинал (англ.) Python API RESTs With Flask, Connexion, and SQLAlchemy

Опубликовано Вадим В. Костерин

Ст.преп. кафедры ИТЭ. Автор более 130 научных и учебно-методических работ. Лауреат ВДНХ (серебряная медаль).

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *