Как написать api на python
Перейти к содержимому

Как написать api на python

  • автор:

Как создать API с помощью Python и Django

API, Application Programming Interface (программный интерфейс приложения), — очень широкое понятие в бэкенд-разработке. Тот API, который мы рассмотрим сегодня, представляет собой сайт без фронтенд-составляющей. Вместо рендеринга HTML-страниц, бэкенд возвращает данные в JSON формате для использования их в нативных или веб-приложениях. Самое пристальное внимание при написании API (как и при написании вебсайтов) нужно обратить на то, как он будет использоваться. Сегодня мы поговорим о том, как использовать Django для создания API для простого приложения со списком дел.

Нам понадобится несколько инструментов. Для выполнения всех шагов я бы рекомендовал вам, вместе с данной статьей, клонировать вот этот учебный проект из GitHub-репозитория. Также вы должны установить Python 3, Django 2.2, и djangorestframework 3.9 (из репозитория запустите pip install -r requirements.txt для установки библиотек). Если не все будет понятно с установкой Django, можно воспользоваться официальной документацией. Также вам нужно будет скачать бесплатную версию Postman. Postman – отличный инструмент для разработки и тестирования API, но в этой статье мы воспользуемся лишь его самыми базовыми функциями.

Для начала откройте папку taskmanager , содержащую manage.py , и выполните python manage.py migrate в командной строке, чтобы применить миграции баз данных к дефолтной sqlite базе данных Django. Создайте суперпользователя с помощью python manage.py createsuperuser и не забудьте записать имя пользователя и пароль. Они понадобятся нам позже. Затем выполните python manage.py runserver для взаимодействия с API.

Вы можете работать с API двумя способами: просматривая фронтенд Django REST фреймворка или выполняя http-запросы. Откройте браузер и перейдите к 127.0.0.1:8000 или к localhost через порт 8000, где Django-проекты запускаются по умолчанию. Вы увидите веб-страницу со списком доступных конечных точек API. Это важнейший принцип в RESTful подходе к API-разработке: сам API должен показывать пользователям, что доступно и как это использовать.

Сначала давайте посмотрим на функцию api_index в views.py. Она содержит список конечных точек, которые вы посещаете.

 @define_usage(returns='url_usage': 'Dict'>) @api_view(['GET']) @permission_classes((AllowAny,)) def api_index(request): details = <> for item in list(globals().items()): if item[0][0:4] == 'api_': if hasattr(item[1], 'usage'): details[reverse(item[1].__name__)] = item[1].usage return Response(details) 

API функции для каждого представления (view в Django) обернуты тремя декораторами. Мы еще вернемся к @define_usage . @api_view нужен для Django REST фреймворка и отвечает за две вещи: шаблон для веб-страницы, которая в результате получится, и HTTP-метод, поддерживаемый конечной точкой. Чтобы разрешить доступ к этому url без проверки подлинности, @permission_classes , также из Django REST фреймворка, задан как AllowAny . Главная функция API обращается к глобальной области видимости приложения чтобы «собрать» все определенные нами функции. Так как мы добавили к каждой функции представления префикс api_ , мы можем легко их отфильтровать и вернуть словарь, содержащий информацию об их вызовах. Детали вызовов предоставляются пользовательским декоратором, написанным в decorators.py.

 def define_usage(params=None, returns=None): def decorator(function): cls = function.view_class header = None # Нужна ли аутентификация для вызова этого представления? if IsAuthenticated in cls.permission_classes: header = 'Authorization': 'Token String'> # Создаем лист доступных методов, исключая 'OPTIONS' methods = [method.upper() for method in cls.http_method_names if method != 'options'] # Создаем словарь для ответа usage = 'Request Types': methods, 'Headers': header, 'Body': params, 'Returns': returns> # Защита от побочных эффектов @wraps(function) def _wrapper(*args, **kwargs): return function(*args, **kwargs) _wrapper.usage = usage return _wrapper return decorator 

Декоратор — часть синтаксиса, которая позволяет легко определять функции высокого порядка, чтобы добавить функциям представления атрибуты (как классам). Представления на основе функций с декораторами — отличный компромисс между простыми функциями и представлениями на основе классов в Django. Этот декоратор предоставляет четыре информационных элемента: типы запросов, заголовки, параметры и возвращаемое значение каждой функции. Декоратор генерирует заголовок и информацию о методе на основе информации, полученной от других декораторов, прикрепленных к функции, и принимает в качестве входных данных параметры и возвращаемые значения на момент вызова данного декоратора.

Помимо вывода результатов index-запроса, мы также будем использовать наш API для взаимодействия с данными пользователя, так что нам понадобится какой-то способ аутентификации. Если бы это был не просто учебный проект, а что-то посерьезнее, можно было бы реализовать регистрацию пользователей (к тому же, это отличная практика, если вы хотите проверить, насколько вы разобрались с понятиями из этой статьи). Но вместо этого мы просто войдем под учетной записью суперпользователя, которую создали заранее.

 @define_usage(params='username': 'String', 'password': 'String'>, returns='authenticated': 'Bool', 'token': 'Token String'>) @api_view(['POST']) @permission_classes((AllowAny,)) def api_signin(request): try: username = request.data['username'] password = request.data['password'] except: return Response('error': 'Please provide correct username and password'>, status=HTTP_400_BAD_REQUEST) user = authenticate(username=username, password=password) if user is not None: token, _ = Token.objects.get_or_create(user=user) return Response('authenticated': True, 'token': "Token " + token.key>) else: return Response('authenticated': False, 'token': None>) 

Важно отметить, что для того, чтобы идентификация на основе токенов заработала, нужно настроить несколько параметров. Гид по настройке можно найти в файле settings.py учебного проекта.

Чтобы верифицировать пользователя, метод api_signin запрашивает имя пользователя и пароль и использует встроенный в Django метод authenticate . Если предоставленные учетные данные верны, он возвращает токен, позволяющий клиенту получить доступ к защищенным конечным точкам API. Помните о том, что данный токен предоставляет те же права доступа, что и пароль, и поэтому должен надежно храниться в клиентском приложении. Теперь мы наконец можем поработать с Postman. Откройте приложение и используйте его для отправки post-запроса к /signin/, как показано на скриншоте.

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

 class Task(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) #Каждая задача принадлежит только одному пользователю description = models.CharField(max_length=150) #У каждой задачи есть описание due = models.DateField() #У каждой задачи есть дата выполнения, тип datetime.date 

Модель Task представляет собой довольно простой подход к менеджменту задач нашего приложения. Каждый элемент имеет описание, например, «Написать API с помощью Django» и дату выполнения. Задачи также связаны внешним ключом с объектом Django User , что означает, что каждая задача принадлежит только одному конкретному пользователю, но каждый пользователь может иметь неограниченное количество задач или не иметь вовсе. Каждый объект Django также имеет идентификатор, уникальное целое число, которое можно использовать для ссылки на индивидуальные задачи.

Приложения типа этого часто называют CRUD-приложениями, от «Create, Read, Update, Destroy» (Создание, Чтение, Модификация, Удаление), четырех операций, поддерживаемых нашим приложением на объектах Task.

Для начала создадим пустой список задач, связанных с конкретным пользователем. Используйте Postman для создания GET-запроса к /all/, как на скриншоте ниже. Не забудьте добавить токен к заголовкам этого и всех последующих запросов.

 @define_usage(returns='tasks': 'Dict'>) @api_view(['GET']) @authentication_classes((SessionAuthentication, BasicAuthentication, TokenAuthentication)) @permission_classes((IsAuthenticated,)) def api_all_tasks(request): tasks = taskSerializer(request.user.task_set.all(), many=True) return Response('tasks': tasks.data>) 

Функция api_all_tasks довольно проста. Стоит обратить внимание лишь на смену требований к проверке подлинности и классов разрешения на аутентификацию токеном. У нас есть новый декоратор @authentication_classes , позволяющий выполнять как дефолтные методы аутентификации Django REST framework, так и TokenAuthentication . Это позволяет нам ссылаться на все экземпляры User как на request.user , как если бы пользователи залогинились через стандартную Django-сессию. Декоратор @define_usage показывает нам, что api_all_tasks не принимает параметров (в отличие от GET-запроса) и возвращает лишь одну вещь — список задач. Поскольку данная функция возвращает данные в формате JSON (JavaScript Object Notation), мы используем сериализатор, чтобы сообщить Django, как парсить данные для отправки.

 class taskSerializer(serializers.ModelSerializer): class Meta: model = Task fields = ('id', 'description', 'due') 

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

 @define_usage(params='description': 'String', 'due_in': 'Int'>, returns='done': 'Bool'>) @api_view(['PUT']) @authentication_classes((SessionAuthentication, BasicAuthentication, TokenAuthentication)) @permission_classes((IsAuthenticated,)) def api_new_task(request): task = Task(user=request.user, description=request.data['description'], due=date.today() + timedelta(days=int(request.data['due_in']))) task.save() return Response('done': True>) 

Теперь нам нужно создать задачу. Для этого используем api_new_task . Обычно для создания объекта в базе данных используется PUT-запрос. Обратите внимание, что этот метод, как и два других, не требует предварительной сериализации данных. Вместо этого мы передаем параметры в конструктор объекта класса Task, их же мы затем сохраним в базу данных. Мы отправляем количество дней для выполнения задачи, так как это гораздо проще, чем пытаться отправить объект Python-класса Date . Затем в API мы сохраняем какую-нибудь дату в далеком будущем. Чтобы увидеть созданный объект, нужно создать запрос к /new/ для создания задачи и повторить запрос к /all/.

 @define_usage(params='task_id': 'Int', 'description': 'String', 'due_in': 'Int'>, returns='done': 'Bool'>) @api_view(['POST']) @authentication_classes((SessionAuthentication, BasicAuthentication, TokenAuthentication)) @permission_classes((IsAuthenticated,)) def api_update_task(request): task = request.user.task_set.get(id=int(request.data['task_id'])) try: task.description = request.data['description'] except: #Обновление описания необязательно pass try: task.due = date.today() + timedelta(days=int(request.data['due_in'])) except: #Обновление даты выполнения необязательно pass task.save() return Response('done': True>) 

Для редактирования только что созданной задачи нужно создать POST-запрос к api_update_task через /update/. Мы включаем task_id для ссылки на правильную задачу из пользовательского task_set . Код здесь будет немного сложнее, т.к. мы хотим иметь возможность обновлять описания и/ или дату выполнения задачи.

 @define_usage(params='task_id': 'Int'>, returns='done': 'Bool'>) @api_view(['DELETE']) @authentication_classes((SessionAuthentication, BasicAuthentication, TokenAuthentication)) @permission_classes((IsAuthenticated,)) def api_delete_task(request): task = request.user.task_set.get(id=int(request.data['task_id'])) task.delete() return Response('done': True>) 

Используйте DELETE-запрос к api_delete_task через /delete/ для удаления задачи. Этот метод работает аналогично функции api_update_task , за исключением того, что вместо изменения задачи он удаляет ее.

Сегодня мы с вами разобрались, как реализовать index-запрос, аутентификацию на основе токенов и четыре основных HTTP-метода для Django API. Вы можете использовать эти знания для поддержки любых веб- и нативных мобильных приложений или для разработки публичного API для обмена данными. Не стесняйтесь клонировать учебный проект, содержащий весь код, представленный в этой статье, и попробуйте реализовать такие расширения как пагинация, ограничение числа запросов и создание пользователя.

© Copyright 2014 — 2023 mkdev | Privacy Policy

Как написать api на python

Рассмотренного в прошлых темах материала достаточно для создания примитивного приложения. В этой теме попробуем реализовать простейшее приложение Web API в стиле REST. Архитектура REST предполагает применение следующих методов или типов запросов HTTP для взаимодействия с сервером, где каждый тип запроса отвечает за определенное действие:

  • GET (получение данных)
  • POST (добавление данных)
  • PUT (изменение данных)
  • DELETE (удаление данных)

Для каждого из этих типов запросов класс FastAPI предоставляет соответствующие методы. Рассмотрим, как мы можем реализовать с помощью этих методов простейший API. Пусть у нас будет следующий проект:

Создание Web API на FastAPI и Python

Создание сервера

В файле main.py определим следующий код:

import uuid from fastapi import FastAPI, Body, status from fastapi.responses import JSONResponse, FileResponse class Person: def __init__(self, name, age): self.name = name self.age = age self.id = str(uuid.uuid4()) # условная база данных - набор объектов Person people = [Person("Tom", 38), Person("Bob", 42), Person("Sam", 28)] # для поиска пользователя в списке people def find_person(id): for person in people: if person.id == id: return person return None app = FastAPI() @app.get("/") async def main(): return FileResponse("public/index.html") @app.get("/api/users") def get_people(): return people @app.get("/api/users/") def get_person(id): # получаем пользователя по id person = find_person(id) print(person) # если не найден, отправляем статусный код и сообщение об ошибке if person==None: return JSONResponse( status_code=status.HTTP_404_NOT_FOUND, content= < "message": "Пользователь не найден" >) #если пользователь найден, отправляем его return person @app.post("/api/users") def create_person(data = Body()): person = Person(data["name"], data["age"]) # добавляем объект в список people people.append(person) return person @app.put("/api/users") def edit_person(data = Body()): # получаем пользователя по id person = find_person(data["id"]) # если не найден, отправляем статусный код и сообщение об ошибке if person == None: return JSONResponse( status_code=status.HTTP_404_NOT_FOUND, content= < "message": "Пользователь не найден" >) # если пользователь найден, изменяем его данные и отправляем обратно клиенту person.age = data["age"] person.name = data["name"] return person @app.delete("/api/users/") def delete_person(id): # получаем пользователя по id person = find_person(id) # если не найден, отправляем статусный код и сообщение об ошибке if person == None: return JSONResponse( status_code=status.HTTP_404_NOT_FOUND, content= < "message": "Пользователь не найден" >) # если пользователь найден, удаляем его people.remove(person) return person

Разберем в общих чертах этот код. Прежде всего для представления данных, с которыми мы будем работать, определяем класс Person .

class Person: def __init__(self, name, age): self.name = name self.age = age self.id = str(uuid.uuid4())

Этот класс содержит три атрибута. Два атрибута — name и age будут представлять имя и возраст пользователя и будут устанавливаться через конструктор. А третий атрибут — id будет служить для уникальной идентификации данного объекта и будет хранить значение guid. Для генерации guid применяется функция uuid.uuid4() из пакета uuid . В конструкторе Person сгенерированный guid преобразуется в строку и присваивается атрибуту id.

Для хранения данных в приложении определим список people, который будет выполнять роль условной базы данных и будет хранить объекты Person.

people = [Person("Tom", 38), Person("Bob", 42), Person("Sam", 28)]

Для поиска объекта Person в этом списке определена вспомогательная функция find_person() .

При обращении к корню веб-приложения, то есть по пути «/», оно будет отправлять в ответ файл index.html , то есть веб-страницу, посредством которой пользователь сможет взаимодействовать с сервером:

@app.get("/") def main(): return FileResponse("public/index.html")

Далее определяются функции, которые собственно и представляют API. Вначале определяется функция, которая обрабатывает запрос типа GET по пути «api/users»:

@app.get("/api/users") def get_people(): return people

Запрос GET предполагает получение объектов, и в данном случае отправляем выше определенный список объектов Person.

Когда клиент обращается к приложению для получения одного объекта по id в запрос типа GET по адресу «api/users/», то срабатывает другая функция:

@app.get("/api/users/") def get_person(id): person = find_person(id) if person==None: return JSONResponse( status_code=status.HTTP_404_NOT_FOUND, content= < "message": "Пользователь не найден" >) return person

Здесь через параметр id получаем из пути запроса идентификатор объекта Person и по этому идентификатору ищем нужный объект в списке people. Если объект по id не был найден, то возвращаем с помощью класса JSONResponse статусный код 404 с некоторым сообщением в формате JSON. Если объект найден, то отправляем найденный объект клиенту.

При получении запроса типа DELETE по маршруту «/api/users/» срабатывает другая функция:

@app.delete("/api/users/") def delete_person(id): person = find_person(id) if person == None: return JSONResponse( status_code=status.HTTP_404_NOT_FOUND, content= < "message": "Пользователь не найден" >) people.remove(person) return person

Здесь действует аналогичная логика — если объект по id не найден, отправляет статусный код 404. Если же объект найден, то удаляем его из списка и посылаем клиенту.

При получении запроса с методом POST по адресу «/api/users» срабатывает следующая функция:

@app.post("/api/users") def create_person(data = Body()): person = Person(data["name"], data["age"]) people.append(person) return person

Запрос типа POST предполагает передачу приложению отправляемых данных. Причем мы ожидаем, что клиент отправит данные, которые содержат значения name и age. Для краткости мы пока опускаем валидацию входных данных. И для получения данных из тела запроса с помощью класса Body получаем данные в параметр data и затем используем данные из этого параметра для создания объекта Person. Затем созданный объект добавляется в список people и отправляется назад клиенту.

Если приложению приходит PUT-запрос по адресу «/api/users», то аналогичным образом получаем отправленные клиентом данные в виде объекта Person и пытаемся найти подобный объект в списке people. Если объект не найден, отправляем статусный код 404. Если объект найден, то изменяем его данные и отправляем обратно клиенту:

@app.put("/api/users") def edit_person(data = Body()): person = find_person(data["id"]) if person == None: return JSONResponse( status_code=status.HTTP_404_NOT_FOUND, content= < "message": "Пользователь не найден" >) person.age = data["age"] person.name = data["name"] return person

Таким образом, мы определили простейший API. Теперь добавим код клиента.

Определение клиента

Теперь в проекте определим папку public , в которую добавим новый файл index.html

Определим в файле index.html следующим код для взаимодействия с сервером FastAPI:

    METANIT.COM td button 

Список пользователей

Имя:

Возраст:

ИмяВозраст

Основная логика здесь заключена в коде javascript. При загрузке страницы в браузере получаем все объекты из БД с помощью функции getUsers() :

async function getUsers() < // отправляет запрос и получаем ответ const response = await fetch("/api/users", < method: "GET", headers: < "Accept": "application/json" >>); // если запрос прошел нормально if (response.ok === true) < // получаем данные const users = await response.json(); const rows = document.querySelector("tbody"); // добавляем полученные элементы в таблицу users.forEach(user =>rows.append(row(user))); > >

Для добавления строк в таблицу используется функция row() , которая возвращает строку. В этой строке будут определены ссылки для изменения и удаления пользователя.

Ссылка для изменения пользователя с помощью функции getUser() получает с сервера выделенного пользователя:

async function getUser(id) < const response = await fetch(`/api/users/$`, < method: "GET", headers: < "Accept": "application/json" >>); if (response.ok === true) < const user = await response.json(); document.getElementById("userId").value = user.id; document.getElementById("userName").value = user.name; document.getElementById("userAge").value = user.age; >else < // если произошла ошибка, получаем сообщение об ошибке const error = await response.json(); console.log(error.message); // и выводим его на консоль >>

И выделенный пользователь добавляется в форму над таблицей. Эта же форма применяется и для добавления объекта. С помощью скрытого поля, которое хранит id пользователя, мы можем узнать, какое действие выполняется — добавление или редактирование. Если id не установлен (равен пустой строке), то выполняется функция createUser, которая отправляет данные в POST-запросе:

async function createUser(userName, userAge) < const response = await fetch("api/users", < method: "POST", headers: < "Accept": "application/json", "Content-Type": "application/json" >, body: JSON.stringify(< name: userName, age: parseInt(userAge, 10) >) >); if (response.ok === true) < const user = await response.json(); document.querySelector("tbody").append(row(user)); >else < const error = await response.json(); console.log(error.message); >>

Если же ранее пользователь был загружен на форму, и в скрытом поле сохранился его id, то выполняется функция editUser, которая отправляет PUT-запрос:

async function editUser(userId, userName, userAge) < const response = await fetch("api/users", < method: "PUT", headers: < "Accept": "application/json", "Content-Type": "application/json" >, body: JSON.stringify(< id: userId, name: userName, age: parseInt(userAge, 10) >) >); if (response.ok === true) < const user = await response.json(); document.querySelector(`tr[data-rowid='$']`).replaceWith(row(user)); > else < const error = await response.json(); console.log(error.message); >>

И функция deleteUser() посылает на сервер запрос типа DELETE на удаление пользователя, и при успешном удалении на сервере удаляет объект по id из списка объектов Person.

Теперь запустим проект, и по умолчанию приложение отправит браузеру веб-страницу index.html , которая загрузит список объектов:

взаимодействие javascript с Web API на FastAPI и Python

После этого мы сможем выполнять все базовые операции с пользователями — получение, добавление, изменение, удаление. Например, добавим нового пользователя:

Лучший фреймворк для API на Python

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

Денис Расулев · Sep 10, 2023 ·

/images/2022/what-is-api.jpg

Лучший фреймворк для разработки API на Python.

Это вторая статья из серии, посвященной теме API.

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

  1. Простое объяснение API
  2. Лучший фреймворк для API (эта статья ��)
  3. Пишем API используя FastAPI (скоро)
  4. Пишем API с помощью ChatGPT (скоро)
  5. Инструменты тестирования API (скоро)
  6. Зарабатываем деньги на API (скоро)

Фреймворки для API

В предыдущей статье мы разобрались, что такое API и как это работает, так что теперь давай посмотрим как выбрать лучший фреймворк для API на Python. Чтобы подобрать инструмент, который позволит быстро и эффективно написать API на Python, необходимо учитывать следующие вещи:

  • Размер проекта. Если твой API будет частью полноценного веб-приложения, то лучше выбирать фреймворк, который позволит создать как само веб-приложение, так и его API часть. Если же все, что тебе нужно — это только API, то подойдет и любой из микро фреймворков.
  • Рабочая нагрузка. Обычно это напрямую определяется требованиями к процессорной мощности и объему памяти на сервере. Наиболее очевидным параметром является количество запросов клиент-сервер, которое сможет обработать сервер.
  • Время освоения. Как правило, чем мощее и производительнее фреймворк, тем больше времени требуется на его изучение. Если ты уже хорошо владеешь каким-либо инструментом, то, разумеется, этот параметр можно не принимать во внимание.

Особняком стоит простой случай, когда все что нужно — это клиент для получения данных от уже существующего API. Для его создания вполне может хватить встроенного модуля или любой из популярных библиотек, например, httplib2 или всеми любимой requests. Хоть это и не относится напрямую к теме, но их мы тоже рассмотрим для полноты картины.

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

  • Библиотеки для написания клиента (библиотека клиента)
  • Микро фреймворки (минимальный набор функций)
  • Полнофункциональные фреймворки (full stack).

Начнем с простого…

Библиотеки клиентов

Requests

Тип: Библиотека клиента

Скриншот официальной страницы библиотеки Requests

Requests — это очень популярная клиентская библиотека HTTP в Python. Даже официальная документация Python рекомендует ее. Как следует из её названия, она используется для выполнения запросов к API. Библиотека поддерживает все методы и расширенные возможности HTTP, такие как аутентификация, сессионные куки, работа с SSL и многие другие.

Работать с requests очень просто. Вот пример вызова API в Python, когда используется метод GET для авторизации на сайте:

 1 2 3 4 5 6 7 8 9 10 11 12 13 
>>> import requests >>> URL = 'https://httpbin.org/basic-auth/user/pass' >>> r = requests.get(URL, auth=('user', 'pass')) >>> r.status_code 200 >>> r.headers['content-type'] 'application/json; charset=utf8' >>> r.encoding 'utf-8' >>> r.text ' >>> r.json() 'authenticated': True, . > 

Подробную документацию по этой библиотеке смотри здесь.

Faster Than Requests

Тип: Библиотека клиента

Примеры команд библиотеки Faster Than Requests

Довольно любопытный пакет, который активно развивается. По заявлениям разработчика работает быстрее, чем Requests 🙂 Возможно это потому, что для разработки используется главным образом язык Nim. Сравнение производительности есть на главной странице репозитория GitHub. Также утверждается, что библиотека намного компактнее по количеству строчек кода.

Самое удобное в этой библиотеке — это множество вспомогательных функций, выходящих за рамки обычных методов HTTP. В ней есть несколько удобных функций для таких задач, как поиск URL-адресов, загрузка ресурсов, например файлов изображений, или объединение запросов к нескольким URL-адресам и возвращение одного ответа.

Вот несколько примеров стандартных запросов API на Python:

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 
import faster_than_requests as requests  # GET requests.get("http://httpbin.org/get")  # POST requests.post("http://httpbin.org/post", "Some Data Here")  # Download a file requests.download("http://example.com/foo.jpg", "out.jpg")  # Multi-Threaded Web Scraper requests.scraper(["http://foo.io", "http://bar.io"], threads=True)  # URL-to-SQLite Web Scraper requests.scraper5("http://foo.io", sqlite_file_path="database.db")  # Regex-powered Web Scraper requests.scraper6("http://python.org", "(www|http:|https:)+[^s]+[w]")  # CSS Selector Web Scraper requests.scraper7("http://python.org", "body > div.someclass a#someid")  # WebSockets Binary/Text requests.websocket_send("ws://echo.websocket.org", "data here") 
PycURL

Тип: Библиотека клиента

Скриншот Документация PycURL

PycURL — это просто Python надстройка для библиотеки libcurl, которая служит для передачи файлов по различным протоколам. Она поддерживает HTTP, FTP, SMTP и многие другие. Если тебе нравятся библиотеки cURL или libcurl, то возможно тебе придется по вкусу и этот питоновский интерфейс для нативной библиотеки libcurl, написанной на C/C++.

Много интересного ты найдешь в официальном репозитории PycURL на GitHub. Для более подробного ознакомления с библиотекой также почитай официальную документацию.

Ниже пример того, как можно выполнить вызов HTTP GET с помощью PycURL.

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 
import pycurl from io import BytesIO  buffer = BytesIO() c = pycurl.Curl() c.setopt(c.URL, 'http://pycurl.io/') c.setopt(c.WRITEDATA, buffer) c.perform() c.close() body = buffer.getvalue() # Body - это байтовая строка. # Нужно знать кодировку, чтобы вывести ее в текстовый файл, # например, в стандартный вывод. print(body.decode('iso-8859-1')) 
urllib3

Тип: Библиотека клиента

Скриншот urllib3 Homepage

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

urllib3 — это мощный и удобный для использования HTTP клиент для Python. Функциональные возможности библиотеки позволяют организовать быструю и надежную работу практически с любыми источниками информации в интернете.

Большая часть экосистемы Python уже пользуется urllib3, так что и ты можешь приглядеться к этой библиотеке.

Примеры вызовов API на Python в библиотеке urllib3:

1 2 3 4 5 6 7 8 9 
>>> import urllib3 >>> http = urllib3.PoolManager(num_pools=2) >>> resp = http.request('GET', 'http://yahoo.com/') >>> resp = http.request('GET', 'http://google.com/') >>> resp = http.request('GET', 'http://httpbin.org/robots.txt') >>> resp.status 200 >>> resp.data b"User-agent: *\nDisallow: /deny\n" 

Микро фреймворки

Flask

Тип: Микро фреймворк

Скриншот Документация Flask

Проект начинался как простая обертка вокруг Werkzeug и Jinja, и на сегодняшний день стал одним из самых популярных фреймворков для разработки веб-приложений на Python, включая создание API. Репозиторий проекта на GitHub имеет уже более 60 тысяч звезд. Flask позволяет легко начать, быстро получить первые результаты и постепенно масштабировать твое приложение до любого уровня.

За прошедшие годы Flask пополнился множеством функций, что ставит его практически на один уровень с полностековыми (full stack) фреймворками. Однако именно его минималистичный подход к созданию веб-приложений делает его предпочтительным выбором для многих разработчиков.

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

Обратная сторона гибкости

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

Для начала тебе поможет подборка официальных шаблонов. Также обрати внимание на встроенную концепцию Flask под названием Blueprints, которые по сути являются эквивалентом модулей Python во Flask.

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

Вот так можно написать простейшее веб-приложение “Hello World” на Flask:

 1 2 3 4 5 6 7 8 9 10 
from flask import Flask  app = Flask(__name__)  @app.route('/') def hello_world():  return 'Hello, World!'  if __name__ == '__main__':  app.run() 

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

Также рекомендую официальный туториал от самого Miguel Grinberg, отличную серию статей на Hackers and Slackers и сообщество пользователей на Reddit.

На русском языке рекомендую перевод официального туториала на Habr.

Tornado

Тип: Микро фреймворк

Скриншот Tornado Homepage

Tornado — это фреймворк и асинхронная сетевая библиотека. Он также включает в себя HTTP сервер и клиентский интерфейс, а также интерфейс WebSocket для двухстороннего взаимодействия с серверами, поддерживающими WebSocket.

Tornado поддерживает все основные функции промежуточного ПО, необходимые для обработки HTTP запросов и ответов, шаблонов и маршрутизации.

В нем также поддерживаются корутины (совместные маршруты), что делает его отличным инструментом для создания бэкендов серверов с длительным циклом получения данных и постоянными соединениями, особенно для WebSockets.

Что такое корутины

Корутины — это облегчённые потоки. Облегчённый поток означает, что он не привязан к нативному потоку, не требует переключения контекста на процессор, и поэтому он быстрее.

Подобно потокам, корутины могут работать параллельно, ждать друг друга и общаться. Самое большое различие заключается в том, что корутины очень дешевые, почти бесплатные: их можно создавать тысячами и платить очень мало с точки зрения производительности. А вот тысяча потоков может стать серьезной проблемой даже для современной машины.

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

Корутины поддерживают Kotlin, JavaScript, PHP, C#, Go, Python, Ruby, Lua и другие языки программирования.

Простой бэкенд для API в Tornado можно сделать следующим образом:

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
import asyncio import tornado.web  class MainHandler(tornado.web.RequestHandler):  def get(self):  self.write("Hello, world")  def make_app():  return tornado.web.Application([  (r"/", MainHandler),  ])  async def main():  app = make_app()  app.listen(8888)  await asyncio.Event().wait()  if __name__ == "__main__":  asyncio.run(main()) 

Tornado существует уже давно, но некоторые его функции немного устарели по сравнению с современными REST-фреймворками. Тем не менее, он пользуется большой популярностью, поскольку у репозитория на GitHub почти 21 тысяча звезд.

FastAPI

Тип: Микро фреймворк

Скриншот FastAPI Homepage

FastAPI — это один из новых фреймворков Python. По утверждениям разработчиков, он является очень быстрым, высокопроизводительным и поддерживает компактную структуру кодирования, что приводит к очень быстрой разработке приложений.

FastAPI основан на возможностях asyncio в Python, которые были стандартизированы как спецификация ASGI для создания асинхронных веб-приложений. По своим возможностям FastAPI почти не уступает Flask и поддерживает встроенные процедуры для интеграции с базами данных, выполнения фоновых задач, подключения кастомного промежуточного программного обеспечения и многое другое.

Имея более 50 тысяч звезд у репозитория на GitHub, FastAPI завоевывает всё большую популярность в сообществе Python и постоянно развивается группой активных профессионалов из более чем 100 человек.

Вот как можно создать простой REST API с помощью FastAPI:

 1 2 3 4 5 6 7 8 9 10 11 
from fastapi import FastAPI  app = FastAPI()  @app.get("/") def read_root():  return "Hello": "World">  @app.get("/items/ ") def read_item(item_id: int, q: str = None):  return "item_id": item_id, "q": q> 

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

Sanic

Тип: Микро фреймворк

Скриншот Sanic Homepage

Sanic — это еще один веб-фреймворк Python на основе asyncio. Очень легкий фреймворк с поддержкой всех основных функций HTTP и приложений промежуточного программного обеспечения.

Кроме того, Sanic поддерживает возможность написания пользовательских протоколов и компонентов промежуточного ПО для кастомизации протокола обработки запросов и ответов. Sanic имеет свой собственный встроенный веб-сервер для ускорения разработки, а также хорошо интегрируется с Nginx для промышленных приложений.

Вот как написать простой API на Sanic:

 1 2 3 4 5 6 7 8 9 10 11 
from sanic import Sanic from sanic.response import json  app = Sanic()  @app.route('/') async def test(request):  return json('hello': 'world'>)  if __name__ == '__main__':  app.run(host='0.0.0.0', port=8000) 

Для получения более подробной информации посмотри репозиторий Sanic на GitHub или руководство по началу работы.

Falcon

Тип: Микро фреймворк

Лого Falcon Framework

Falcon — это простой и надежный фреймворк для создания бэкендов крупномасштабных приложений и микросервисов. Он поддерживает архитектурный стиль REST и работает с серверами, совместимыми с WSGI или ASGI.

Falcon имеет объектно-ориентированный, основанный на классах интерфейс для определения ресурсов API. Он поддерживает основные функции HTTP и приложений промежуточного программного обеспечения, включая обработку протокола HTTP, маршрутизацию, обработку мультимедиа, cookies и утилиты URI.

Вот как создать REST API, используя объектно-ориентированный подход Falcon:

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 
class QuoteResource:  def on_get(self, req, resp):  """Handles GET requests"""  quote =   'quote': (  "I've always been more interested in "  "the future than in the past."  ),  'author': 'Grace Hopper'  >  resp.media = quote  api = falcon.API() api.add_route('/quote', QuoteResource()) 

Дополнительную информацию найдешь в репозитории Falcon на GitHub. Чтобы начать разработку на Falcon рекомендуется ознакомиться с официальной документацией проекта.

Bottle

Тип: Микро фреймворк

Лого Bottle Framework

Bottle — это очень легкий микрофреймворк. Он имеет совсем небольшой объем, распространяется в виде всего одного файла и зависит только от стандартной библиотеки Python.

Bottle отлично подходит для:

  • Быстрого прототипирования идей
  • Изучения того, как создаются фреймворки
  • Создания и запуска простых личных веб-приложений

Вместе с тем Bottle предоставляет все необходимые компоненты для создания полноценного бэкенда для REST API, который опирается на маршрутизацию и шаблоны. Он поддерживает большинство обычных функций, связанных с HTTP, таких как cookies, заголовки, метаданные и загрузка файлов. Также в нем есть встроенный HTTP сервер.

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

1 2 3 4 5 6 7 
from bottle import route, run, template  @route('/hello/') def index(name):  return template('Hello <>!', name=name)  run(host='localhost', port=8080) 

Подробную информацию смотри в репозитории Bottle на GitHub. В официальной документации ты найдешь руководство по быстрому старту, конфигурационные тонкости и собрание полезных статей.

Hug

Тип: Микро фреймворк

Лого Hug Framework

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

Поскольку нug ориентирован на создание API, его возможности строго ограничены обработкой ввода/вывода, маршрутизацией и аннотациями типов. Однако он поддерживает возможность добавления расширений.

Одной из интересных особенностей нug является возможность предоставления логики API через CLI, HTTP или локальную функцию, что даёт возможность использовать hug в качестве стандартного модуля Python.

Вот как написать API в hug:

1 2 3 4 5 6 
import hug  @hug.get('/happy_birthday') def happy_birthday(name, age:hug.types.number=1):  """Says happy birthday to a user"""  return "Happy  Birthday !".format(**locals()) 

�� Обрати внимание, что при использовании hug может возникнуть проблема, если тебе необходимо предварительно обрабатывать получаемые запросы. Поскольку тело запроса передается в потоке, то прочитать его можно только один раз.

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

Подробную информацию ты найдешь в репозитории hug на GitHub, а также в официальной документации.

Eve

Тип: Микро фреймворк

Скриншот Eve Homepage

Eve — это микрофреймворк для API, построенный на базе Flask. Цель Eve — сделать разработку REST API чрезвычайно быстрой и простой. Поэтому он построен на принципах Flask, оставляя в стороне все компоненты веб-приложений Flask.

Eve поддерживает все наиболее используемые шаблоны интерфейса REST API, такие как CRUD-операции, настраиваемые концевые точки API, фильтрация, сортировка, многостраничность, форматы JSON/XML/JSONP.

Он также поддерживает расширенные возможности, такие как аутентификация, CORS, кэширование, ограничение скорости и многое другое. Eve также поддерживает интеграцию с базами данных MongoDB и SQL.

В Eve для определения ресурсов и конечных точек API может использоваться конфигурационный файл в формате Python. Таким образом, REST API может быть построен с использованием декларативного синтаксиса JSON.

Для более подробной информации прочитай руководство по быстрому запуску Eve или посмотри репозиторий GitHub.

Фулстек фреймворки

Django

Тип: Фулстек фреймворк

Лого Django Framework

Django — это полнофункциональный, полностековый веб-фреймворк на языке Python. Это один из старейших и самых популярных веб-фреймворков, у репозитария которого почти 67 тысяч звезд на GitHub.

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

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

Загляни в официальный репозиторий Django и/или официальный репозитарий Django REST, чтобы получить более подробную информацию о работе с ними. А по этой ссылке ты найдешь Руководство по быстрому старту с Django REST.

TurboGears

Тип: Фулстек фреймворк

Лого Turbogears Framework

TurboGears — это еще один полностековый фреймворк. Основная идея при его разработке состояла в том, чтобы дать возможность масштабировать проект от простого приложения (в одном файле) до приложения полного стека. Таким образом, TurboGears может создавать ощущение работы с микрофреймворком, но при этом он предоставляет все необходимые инструменты для разработки полноценного веб-приложения.

TurboGears построен по схеме MVC (Model-View-Controller или “Модель-Представление-Контроллер”), как и другие полнофункциональные фреймворки. Он поддерживает шаблоны, управление страницами, аутентификацию и авторизацию, кэширование, а также поддержку различных баз данных и миграцию схем.

Самый базовый вариант создается очень просто. Сделай файл tgapp.py и объяви в нем контроллер:

1 2 3 4 5 6 7 8 
class RootController(TGController):  @expose()  def index(self):  return 'Hello World'   @expose()  def hello(self, person):  return 'Hello %s' % person 

Чтобы контроллер работал, нужно создать приложение:

1 2 3 4 5 6 7 8 
from tg import MinimalApplicationConfigurator  config = MinimalApplicationConfigurator() config.update_blueprint(  'root_controller': RootController() >)  application = config.make_wsgi_app() 

И наконец, дать команду на запуск этого приложения:

1 2 3 4 5 
from wsgiref.simple_server import make_server  print("Serving on port 8080. ") httpd = make_server('', 8080, application) httpd.serve_forever() 

Потом запускаешь приложение командой python tgapp.py и оно стартанет сервер на порту 8080. Открой браузер, вбей адрес http://localhost:8080 и увидишь свой текст Hello, world .

А если отправишь запрос http://localhost:8080/hello?person=MyName , то увидишь ответ Hello MyName .

Посмотри репозиторий TurboGears на GitHub, чтобы разобраться лучше с этим фреймворком. А для начала работы изучи документацию TurgoGears.

web2py

Тип: Фулстек фреймворк

Screenshot of Web2Py Homepage

Web2py — это опенсорсный полностековый фреймворк, написанный и программируемый на Python. Его основная цель — это разработка быстрых, масштабируемых и безопасных веб приложений на основе баз данных.

В основе web2py лежат модули для работы с HTTP и URL. Он также имеет встроенный планировщик для выполнения фоновых задач. Кроме того, web2py имеет слой абстракции базы данных, который отображает объекты Python в объекты базы данных, такие как таблицы, запросы и записи.

Уровень абстракции базы данных работает в сочетании с набором драйверов, поддерживающих многие популярные базы данных, такие как SQLite, MySQL, PostgreSQL, Oracle, DB2, MSSQL, MongoDB и другие.

В нем также есть полнофункциональная поддержка MVC, валидация форм, безопасность, контроль доступа и многие другие утилиты.

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

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

Pyramid

Тип: Фулстек фреймворк

Лого Pyramid Framework

Pyramid — это еще один полнофункциональный веб-фреймворк Python, основная идея которого заключается в том, чтобы начать с малого и по мере необходимости вырасти до большого проекта. Такой подход позволяет разработчикам начать с Pyramid как с микро-фреймворка.

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

Pyramid включает все стандартные функции веб-фреймворка, такие как схема MVC, маршрутизация, шаблоны, безопасность, сессии, базы данных и протоколирование. Он также имеет встроенный веб-сервер под названием pserve, но без проблем работает с Apache и Nginx для серьезных приложений.

Вот пример простого бэкенда на Pyramid.

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 
from wsgiref.simple_server import make_server from pyramid.config import Configurator from pyramid.response import Response  def hello_world(request):  return Response('Hello World!')  if __name__ == '__main__':  with Configurator() as config:  config.add_route('hello', '/')  config.add_view(hello_world, route_name='hello')  app = config.make_wsgi_app()  server = make_server('0.0.0.0', 6543, app)  server.serve_forever() 

Как и в предыдущих случаях, рекомендую ознакомится с репозитарием проекта на GitHub, посмотреть руководство по быстрому старту и почитать официальную документацию Pyramid.

Заключение

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

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

Каждый фреймворк работает в реалистичной конфигурации. Результаты получены на облачных инстансах и на физическом оборудовании. Тестовые реализации в основном созданы сообществом, а все исходные тексты доступны в репозитории GitHub.

В следующей части мы рассмотрим практический пример того, как написать свой API и в дальнейшем правильно его задокументировать.

Как создать RESTful API на Python

Узнайте, как создать RESTful API на Python с использованием Flask, для легкого взаимодействия с системами и сервисами.

A developer building an API with Python.

Алексей Кодов
Автор статьи
23 июня 2023 в 18:42

Создание RESTful API на Python является важным навыком для любого разработчика, поскольку API играют центральную роль в современных веб-приложениях. В этой статье мы рассмотрим основы создания RESTful API с использованием Python и популярного фреймворка Flask.

Что такое RESTful API?

RESTful API (Representational State Transfer) — это архитектурный стиль, который определяет набор ограничений для создания веб-сервисов. RESTful API позволяют разработчикам легко взаимодействовать с различными системами и сервисами, используя стандартные HTTP-методы, такие как GET, POST, PUT и DELETE.

Подготовка окружения

Для начала установим фреймворк Flask:

pip install Flask

Теперь создадим новый файл app.py и импортируем необходимые модули:

from flask import Flask, jsonify, request app = Flask(__name__)

В этом примере мы используем функцию jsonify для преобразования словаря Python в JSON-объект.

Создание маршрутов

Для создания RESTful API нам нужно определить маршруты, которые будут обрабатывать HTTP-запросы. Воспользуемся декоратором @app.route для определения маршрутов:

@app.route('/api/v1/tasks', methods=['GET']) def get_tasks(): tasks = [ , ] return jsonify()

Здесь мы определили конечную точку /api/v1/tasks с HTTP-методом GET. Эта функция возвращает список задач в формате JSON.

Python-разработчик: новая работа через 9 месяцев
Получится, даже если у вас нет опыта в IT

Запуск приложения

Чтобы запустить наше приложение, добавим следующий код в конец файла app.py :

if __name__ == '__main__': app.run(debug=True)

Теперь, когда мы запустим наше приложение командой python app.py , оно будет доступно по адресу http://127.0.0.1:5000 .

Расширение API

Мы можем расширить наш API, добавив функциональность создания, обновления и удаления задач. Для этого добавим новые маршруты и соответствующие функции:

@app.route('/api/v1/tasks', methods=['POST']) def create_task(): # Здесь будет код для создания задачи @app.route('/api/v1/tasks/<int:task_id>', methods=['PUT']) def update_task(task_id): # Здесь будет код для обновления задачи @app.route('/api/v1/tasks/<int:task_id>', methods=['DELETE']) def delete_task(task_id): # Здесь будет код для удаления задачи

Не забывайте протестировать ваш API с помощью инструментов, таких как Postman или curl.

�� В заключение, создание RESTful API на Python с использованием Flask — относительно простая задача. Следуя приведенным выше примерам, вы сможете создать собственное API для ваших проектов. Удачи в разработке!

Добавить комментарий

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