Comments 32
Мы ранее писали по теме: habrahabr.ru/company/SECL_GROUP/blog/204510/ — Как мы делали API для социальной сети (REST API для WEB)
Делать переводы про клиенты к этому сервису, да и остальных интересных статей по python и flask из этого блога? Я не профессиональный переводчик и не профессиональный python-разработчик — переводы эти делаю для практики языка и для новичков, которые как и я не могут найти в рунете такого же качества информации. Поэтому мой слог может хромать, перевод напоминать гугл-транслейт (хотя максимальная единица автоматического перевода — фраза)), а места расстановки запятых и тире может заставить дергаться глаз филолога. Если кто-то поможет с вычиткой переводов перед публикацией, буду очень признателен.
Про AngularJS в этой связке неплохо бы разжевать, если оно есть в природе.
Есть интересная статься про Django + rest_framework и AngularJS: https://thinkster.io/brewer/angular-django-tutorial/
Ну, вообще Angular ведь совместим на уровне спецификации RESTful, и тут вполне применимы стандартные мануалы по взаимодействию с REST. Единственное отличие — это то, как правильно настроить asset pipeline конкретного фреймворка (а с Flask всё должно быть относительно просто).
Всегда удивляло, почему для создания ресурса используют POST, а для обновления — PUT, семантически логичнее использовать PUT для создания, PATCH — для обновления…
Требования стандарта?
эмм… какого стандарта?
Ну может со словом «стандарт» я перегнул немного.
Однако это общепринятое применение методов.
Можно почитать здесь, здесь книжка в PDF, а вот и статья на хабре.
Прям вот единого сборника требований (спецификации) к RESTful API я не нашел.
Можете сами в гугле поискать. Но везде применение данных методов именно такое.
Однако это общепринятое применение методов.
Можно почитать здесь, здесь книжка в PDF, а вот и статья на хабре.
Прям вот единого сборника требований (спецификации) к RESTful API я не нашел.
Можете сами в гугле поискать. Но везде применение данных методов именно такое.
Если почитать всякие статьи из серии «Делаем фейсбук за неделю», так там вообще пишут, что методов 2 — GET и POST, а остальные есть но не нужны\не используются\что-то из теории.
Дело в том, что на момент создания ресурса его URL зачастую еще не известен, поэтому запрос PUT посылать попросту некуда.
Посылать запрос PUT на URL вида /create или /new нельзя — потому что запрос PUT обязан быть идемпотентным.
Посылать запрос PUT на URL вида /create или /new нельзя — потому что запрос PUT обязан быть идемпотентным.
Пара замечаний по сути статьи:
— после django-rest-framework данный код выглядит как закат солнца вручную, в django-reset-framework можно при помощи десятка строк реализовать полноценный REST API, с pagination, документацией, api browser и поддержкой всех методов
— не рекомендуется в REST API передавать номер версии в url
— после django-rest-framework данный код выглядит как закат солнца вручную, в django-reset-framework можно при помощи десятка строк реализовать полноценный REST API, с pagination, документацией, api browser и поддержкой всех методов
— не рекомендуется в REST API передавать номер версии в url
Вот первое, увы, да. Насколько приятная и компактная штука flask, но аналогов DRF и Tastypie с их магической автоматизацией там совершенно нет.
Это отличное DDD проектирование с возможностью выделения сервисов для SOA, но ничего не мешает загрузить схему БД и написать RESTful сервис самому, что бы было понятнее, с такими маршрутами. Tastypie и DRF прекрасно справляется с этой задачей, но вот нормально выделить ААА сервисы бывает довольно сложно.
Я думаю, а точнее, мне недавно начало казаться, что сравнивать django & flask совсем не нужно. Абсолютно разные фреймоврки, которые хоть и реализуют одну и туже задачу, но делают это с абсолютно разным мировоззрением. :)
В официальной документации есть еще более приятный пример реализации REST API:
flask.pocoo.org/docs/0.10/views/#method-views-for-apis
flask.pocoo.org/docs/0.10/views/#method-views-for-apis
Окошко авторизации возникает совсем не потому, что код ответа 401, а из-за заголовка
WWW-Authenticate
в ответе. Вот здесь есть более подробный ответ. Если вам не нужно выводить это окно пользователю, просто разберитесь, откуда берется этот заголовок и не надо устраивать махинаций с кодами ответа, пожалуйстаНе стоит предлагать городить функциональщину на Python там, где ее не должно быть:
Функцию
Вместо
Команду
Проверку типов необходимо делать с помощью функции
def get_task(task_id):
for task in tasks:
if t['id'] == tasks_id:
return jsonify({'task': task})
abort(404)
Функцию
make_public_task
можно написать проще:def make_public_task(task):
return dict(k, v for k, v in task.items() if k != 'id',
url=url_for('get_task', task_id=task['id'], _external=True))
Вместо
if len(task) == 0
лучше писать просто if not task
.Команду
return None
в конце тела функции писать не нужно — это делается автоматически.Проверку типов необходимо делать с помощью функции
isinstance(obj, cls)
, конкретно в случае со строками используя isinstance(s, basestring)
(актуально для Python 2).Не стоит забывать про метод PATCH. Он предназначен для частичного изменения объекта. На мой взгляд, в большинстве своём он гораздо нужнее, чем PUT.
Спасибо за статью. Не жалею, что прочитал.
Я не очень понимаю как с REST API в python избежать проблемы одновременных обращений.:
Добавим time.sleep(1000), что бы просимулировать медленный ответ REST API и тут начинаются проблемы:
я паралельно запросил curl -i localhost:8888/tasks/2 и curl -i localhost:8888/tasks/1, при этом нет ответа от этих двух запросов.
#python flask/example.py
Подскажите как решается эта проблема?
Добавим time.sleep(1000), что бы просимулировать медленный ответ REST API и тут начинаются проблемы:
@app.route('/tasks/<int:task_id>', methods=['GET'])
def get_task(task_id):
task = filter(lambda t: t['id'] == task_id, tasks)
if len(task) == 0:
abort(404)
if task_id==2:
print "sleeping..."
time.sleep(1000)
return jsonify({'task': task[0]})
я паралельно запросил curl -i localhost:8888/tasks/2 и curl -i localhost:8888/tasks/1, при этом нет ответа от этих двух запросов.
#python flask/example.py
* Running on http://0.0.0.0:8888/
* Restarting with reloader
127.0.0.1 - - [21/Jan/2015 14:06:47] "GET /tasks/3 HTTP/1.1" 404 -
127.0.0.1 - - [21/Jan/2015 14:06:51] "GET /tasks/1 HTTP/1.1" 200 -
sleeping...
Подскажите как решается эта проблема?
Либо куча воркеров и очереди сообщений/задач, либо неблокирующий ioloop и асинхронщина (aiohttp/aiorest, twisted/tornado).
time.sleep() вообще блокирует поток, что и сказано в документации.
Конкретно для фласка есть вот такая штука, но однажды начав писать асинхронный код, я стал смотреть на такие решения с недоумением и от него [фласка] давно убежал.
Вообще WSGI синхронный на уровне архитектуры, т.е. один процесс/поток обрабатывает один запрос.
time.sleep() вообще блокирует поток, что и сказано в документации.
Конкретно для фласка есть вот такая штука, но однажды начав писать асинхронный код, я стал смотреть на такие решения с недоумением и от него [фласка] давно убежал.
Вообще WSGI синхронный на уровне архитектуры, т.е. один процесс/поток обрабатывает один запрос.
Маленькая ошибочка в коде метода GET нужно писать
task = list(filter(lambda t: t['id'] == task_id, tasks))
task = list(filter(lambda t: t['id'] == task_id, tasks))
Sign up to leave a comment.
Проектирование RESTful API с помощью Python и Flask