Создание RESTful API в Google App Engine на основе Flask

в 13:06, , рубрики: api, flask, google app engine, python, RESTful, метки: , , , ,

Создание RESTful API в Google App Engine на основе Flask
Гомес Хульё Марильё де Серванте — известный международный наркобарон, который беспокоится о качестве предоставляемых его организацией услуг. По этому он, Гомес, решил разработать систему online-заказов для своих партнёров.

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

Требования по функционалу к данному API совершенно незначительные. Всего-то принимать заказы. По этому было принято решение использовать REST-подход.
http-протокол, помимо всем известных методов GET и POST, умеет ещё несколько методов, например такие как PUT и DELETE.

При создании RESTful примем следующая договорённость относительно методов:
POST — для создания новых записей.
GET — для получения информации о записи.
PUT — для внесения изменений в запись.
DELETE — для удаления записей.

Гомес Хульё Марильё — очень экономный и технологически продвинутый человек, который знает цену деньгам, не готов платить за услуги больше положенного и знаком с концепцией облачных технологий. По этому выбор сразу же пал на Google App Engine.

А вот его подчинённые-разработчики (т.е. мы) очень ленивые и не хотят делать лишнюю работу. В то же время понимают, что трафика может быть на столько много, что иcпользовать громоздкие решения попросту не экономно. Они сразу же взяли на вооружение Flask.
Нам повезло, ведь Flask для работы с WSGI использует Werkzeug, который прекрастно умеет обрабатывать не только GET и POST, но и PUT и DELETE.

Ваш покорный слуга на основе flask-скелета для app engine создал свой скелет для создания API без блэкджека и женщин.

Сделав форк проекта приступим к его мидификации.
Для начала нам потребуется разработать модель заказа. Заказ характерезуется своим уникальным номером (будет создан по умолчанию), наименованием товара, весом и ключём доступа для модификации. Откроем файл application/models.py удалим всё его содержимое и запишем:
from google.appengine.ext import db

class Order(db.Model):
title = db.StringProperty()
weight = db.FloatProperty()
token = db.StringProperty()

Теперь поработаем с urls.py. Нам необходимо добавить 3 обработчика. Для добавления заказа, получения иформации о заказе и уделения заказа. Сразу после строки:
app.add_url_rule('/', view_func=views.home, methods=['GET',]) # Main page

Добавим строки:
app.add_url_rule('/drug/orders/', view_func=views.add_order, methods=['POST',])
app.add_url_rule('/drug/orders/', view_func=views.get_order, methods=['GET',])
app.add_url_rule('/drug/orders/', view_func=views.delete_order, methods=['DELETE',])

Описание процесса создания формы не буду приводить. Оно достаточно травиально.
Осталось создать 3 соответсвующие функции в views.py. Начнём с добавления заказа:
def add_order():
form = NewOrderForm()

if form.title.data != "":
drug_title = form.title.data
else: return json_response({'error': 'Drug title is empty'})

if form.weight.data != "":
drug_weight = form.weight.data
else: return json_response({'error': 'Drug weight is empty'})

token = str(uuid.uuid4())

order = Order(title = drug_title, weight = float(drug_weight), token = token)
order.put()

return json_response({
'id': int(order.key().id()),
'token': token,
'success': True
})

Запускаем сервер разработки из консоли (перейдите в каталог проекта):
dev_appserver.py project_src/
Проверим работоспособность данной функции:
curl -d "title=drug1&weight=10" localhost:8080/drug/orders/
Результат:
{"token": "2eac6ef6-198b-45a4-bab5-dd2c56d9fb0a", "id": 171, "success": true}
Замечательно. Переходим к созданию функции, которая будет сообщаться нам информацию о заказе:
def get_order():
token = request.args.get('token')
if token is None:
return json_response({'error': 'Token is empty'})

order = Order.all().filter('token = ', token).fetch(1)
if len(order) is 1:
return json_response(order[0]._entity)
else: return json_response({'error': 'Access denied'})

Проверяем:
curl -v -X GET localhost:8080/drug/orders/?token=2eac6ef6-198b-45a4-bab5-dd2c56d9fb0a
Результат:
{"token": "2eac6ef6-198b-45a4-bab5-dd2c56d9fb0a", "weight": 10.0, "title": "value1"}
Последний штрих. Удаление заказа:
def delete_order():
token = request.args.get('token')
if token is None:
return json_response({'error': 'Token is empty'})

order = Order.all().filter('token = ', token).fetch(1)
if len(order) is 1:
order = order[0]
order.delete()
return json_response({'success': True})
else: return json_response({'error': 'Access denied'})

Проверяем:
curl -v -X DELETE localhost:8080/drug/orders/?token=2eac6ef6-198b-45a4-bab5-dd2c56d9fb0a
Результат:
{"success": true}

На всякий случай заглянем в базу данных:
Создание RESTful API в Google App Engine на основе Flask

Ещё раз ссылка на исходники проекта.

Замечание.
Данный набор скриптов хотя и представлен в шуточном виде, может быть расширен до практически любых размеров API-я. Надеюсь, что мне удалось написать не много букв, но при этом дать тебе, %username%, представление о процессе создания RESTful API в облаке.

P.S.
Для упрощения изложения и уменшения количества кода мы немного нарушили REST-принципы. В частности «однозначную идентификацию любого ресура».

Автор: xSkyFoXx

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js