Python digest #1. Новый формат зависимостей и авторизация с помощью Flask


Оглавление (нажмите, чтобы открыть):

Личный кабинет с использованием flask и jinja2

15.02.2020, 22:03

Личный кабинет Flask
Добрый день! Пытаюсь реализовать вход в личный кабинет. Схема входа следующая: *.

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

Джанго. Личный кабинет
Здравствуйте, не могу понять почему во view в методе UserAccountView current_user ничего не.

Как войти в личный кабинет?
Всем привет. Пытаюсь войти в личный кабинет https://sd.tom.ru/ через модуль requests и ничего не.

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

16.02.2020, 09:52 2 16.02.2020, 11:40 [ТС] 3

Но аналогичная функция, срабатывающая при конкретном переходе на test.html работает правильно.

16.02.2020, 13:43 4

lipton_v, https://bitbucket.org/alex925/bulls-. e-view-default вот тебе пример законченного, простого web приложения на flask.
Тебе нужно обратить внимание на декоратор login_required. Он контролирует доступ к заданным частям сайта.

Да и вообще внимательно посмотри на структуру проекта, потому что практически везде в сети примеры с не правильной структурой flask проекта.

22.02.2020, 14:38 5 22.02.2020, 17:52 6

Zigfrid, с того, что:
— при такой архитектуре приложение легко масштабировать;
— проброс объектов выполняется при помощи di (а не циклического импорта пакета, это вообще дикий костыль и неимоверная глупость, которая имеет кучу ограничений), который позволяет делает очень крутые вещи;
— легко искать ошибки, потому что для того, чтобы понять где произошла ошибка не нужно смотреть длиннющий traceback, достаточно посмотреть в адресную строку и увидеть там в каком методе все упало (это + использования flask-classy);
— использование голого sqlalchemy без не нужной обертки (она ничего по сути не делает, она состоит из нескольких строк), позволяет переиспользовать описанную 1 раз в других приложениях (которые могут писаться не на flask). Яркий пример это добавление чата.

Можно ещё написать какие есть плюсы, но мне лень.

22.02.2020, 17:52
22.02.2020, 17:52

Прием json-объекта | Flask, Flask-Security, Telegram-bot
Здравствуйте, помогите , пожалуйста, Flask знаю не очень, но что-то смог, писал бота с бд и.

Создать личный кабинет (Django)
Привет всем. 5 дней изучаю питон, прошу сильно не пинать. Прошел курс на ютуьбе, теперь стараюсь.

Личный кабинет
У меня есть форма авторизации, все ок, все работает, кидает на созданную форму Но теперь задача.

Not Found

The requested URL was not found on the server.

If you entered the URL manually please check your spelling and try again.

Когда мы запросили ресурс с id #2 мы получили его, но вместо ресурса с id #3 мы получили ошибку 404. Такую странную ошибку внутри HTML вместо JSON мы получили, потому, что Flask по умолчанию генерирует страницу с ошибкой 404. Так как это клиентские приложения будут всегда ожидать он нашего сервера JSON, то нам нужно изменить это поведение:

from flask import make_response

@app.errorhandler(404)
def not_found(error):
return make_response(jsonify(<'error': 'Not found'>), 404)

Так мы получим более соответствующий нашему API ответ:

$ curl -i http://localhost:5000/todo/api/v1.0/tasks/3
HTTP/1.0 404 NOT FOUND
Content-Type: application/json
Content-Length: 26
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Mon, 20 May 2013 05:36:54 GMT

Следующий в нашем списке метод POST, который мы будем использовать чтобы добавить новую задачу в нашу базу:

from flask import request

@app.route(‘/todo/api/v1.0/tasks’, methods=[‘POST’])
def create_task():
if not request.json or not ‘title’ in request.json:
abort(400)
task = <
‘id’: tasks[-1][‘id’] + 1,
‘title’: request.json[‘title’],
‘description’: request.json.get(‘description’, «»),
‘done’: False
>
tasks.append(task)
return jsonify(<'task': task>), 201

Добавление новой задачи тоже реализуется довольно просто. request.json содержит данные запроса, но только если они помечены как JSON. Если данных там нет, или данные на месте но отсутствует значение поля title, тогда возвращается код 400, который используется чтобы обозначить «Bad Request».

Затем мы создаем словарь с новой задачей, используя id последней задачи плюс 1(простой способ гарантировать уникальность id в нашей простой базе). Мы терпим отсутствие значения в поле description, и мы предполагаем что поле done при создании задачи всегда будет False.

Мы добавляем новую задачу к нашему массиву tasks, затем возвращаем клиенту сохраненную задачу и код 201, который в HTTP означает «Created».

Чтобы протестировать новую функцию мы используем следующую команду curl:

$ curl -i -H «Content-Type: application/json» -X POST -d ‘<"title":"Read a book">‘ http://localhost:5000/todo/api/v1.0/tasks
HTTP/1.0 201 Created
Content-Type: application/json
Content-Length: 104
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Mon, 20 May 2013 05:56:21 GMT

Примечание: если у вас Windows и вы используете Cygwin версию curl из bash тогда вышеописанная команда сработает как надо. Если вы используете нативную версию curl из обычно командной строки, то придется немного подшаманить с двойными кавычками:

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

Конечно, после выполнения этого запроса мы можем получим обновленный список задач:

$ curl -i http://localhost:5000/todo/api/v1.0/tasks
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 423
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Mon, 20 May 2013 05:57:44 GMT

<
«tasks»: [
<
«description»: «Milk, Cheese, Pizza, Fruit, Tylenol»,
«done»: false,
«id»: 1,
«title»: «Buy groceries»
>,
<
«description»: «Need to find a good Python tutorial on the web»,
«done»: false,
«id»: 2,
«title»: «Learn Python»
>,
<
«description»: «»,
«done»: false,
«id»: 3,
«title»: «Read a book»
>
]
>

Оставшиеся две функции нашего веб-сервиса будут выглядеть так:

@app.route(‘/todo/api/v1.0/tasks/ ‘, methods=[‘PUT’])
def update_task(task_id):
task = filter(lambda t: t[‘ > if len(task) == 0:
abort(404)
if not request.json:
abort(400)
if ‘title’ in request.json and type(request.json[‘title’]) != unicode:
abort(400)
if ‘description’ in request.json and type(request.json[‘description’]) is not unicode:
abort(400)
if ‘done’ in request.json and type(request.json[‘done’]) is not bool:
abort(400)
task[0][‘title’] = request.json.get(‘title’, task[0][‘title’])
task[0][‘description’] = request.json.get(‘description’, task[0][‘description’])
task[0][‘done’] = request.json.get(‘done’, task[0][‘done’])
return jsonify(<'task': task[0]>)

@app.route(‘/todo/api/v1.0/tasks/ ‘, methods=[‘DELETE’])
def delete_task(task_id):
task = filter(lambda t: t[‘ > if len(task) == 0:
abort(404)
tasks.remove(task[0])
return jsonify(<'result': True>)

Функция delete_task без сюрпризов. Для функции update_task мы стараемся предотвратить ошибки делая тщательную проверку входных аргументов. Мы должны убедиться, что предоставленные клиентом данные в надлежащем формате, прежде чем запишем их в базу.

Вызов функци обновляющей задачу с id #2 будет выглядеть примерно так:

$ curl -i -H «Content-Type: application/json» -X PUT -d ‘<"done":true>‘ http://localhost:5000/todo/api/v1.0/tasks/2
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 170
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Mon, 20 May 2013 07:10:16 GMT

<
«task»: [
<
«description»: «Need to find a good Python tutorial on the web»,
«done»: true,
«id»: 2,
«title»: «Learn Python»
>
]
>

Улучшаем интерфейс нашего сервиса

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

Вместо id задачи мы вернем полный URI, через который будет осуществляться выполнение всех действий с задачей. Для этого мы напишем маленькую функцию-хелпер, которая будет генерировать «публичную» версию задачи, отправляемую клиенту:

from flask import url_for

def make_public_task(task):
new_task = <>
for field in task:
if field == ‘id’:
new_task[‘uri’] = url_for(‘get_task’, task_ ], _external=True)
else:
new_task[field] = task[field]
return new_task

Все что мы делаем здесь это берем задачу из нашей базы данных и создаем новую задачу в которой все поля идентичны, за исключением поля id, которое заменено полем uri, сгенерированным функцией url_for предоставляемой Flask.

Когда мы возвращаем список задач мы прогоняем все задачи через эту функцию, прежде чем отослать клиенту:

Теперь клиент получает вот такой список задач:

$ curl -i http://localhost:5000/todo/api/v1.0/tasks
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 406
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Mon, 20 May 2013 18:16:28 GMT

<
«tasks»: [
<
«title»: «Buy groceries»,
«done»: false,
«description»: «Milk, Cheese, Pizza, Fruit, Tylenol»,
«uri»: «http://localhost:5000/todo/api/v1.0/tasks/1»
>,
<
«title»: «Learn Python»,
«done»: false,
«description»: «Need to find a good Python tutorial on the web»,
«uri»: «http://localhost:5000/todo/api/v1.0/tasks/2»
>
]
>

Применив эту технику к остальным функциям мы сможем гарантировать, что клиент всегда получит URI, вместо id.

Защита RESTful веб-сервиса

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

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

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

Простой путь защитить наш веб-сервис это пускать клиентов после авторизации по логину и паролю. В обычном веб-приложении вы должны сделать форму логина, которая отправляет данные авторизации, сервер обрабатывает их и делает новую сессию, а браузер пользователя получает куки с идентификатором сессии. К сожаление здесь мы такое сделать не можем, stateless — одно из правил построения REST веб-сервисов и мы должны просить клиентов отправлять свои регистрационные данные при каждом запросе.

С REST мы всегда стараемся придерживаться протокола HTTP настолько, насколько сможем. Сейчас нам нужно реализовать аутентификацию пользователя в контексте HTTP, который предоставляет нам 2 варианта — Basic и Digest.

Существует маленькое расширение Flask написанное вашим покорным слугой. Давайте установим Flask-HTTPAuth:

$ flask/bin/pip install flask-httpauth

Теперь скажем нашего веб-сервису отдавать данные только пользователю с логином miguel и паролем python. Для начала настроим Basic HTTP authentication как показано ниже:

from flask.ext.httpauth import HTTPBasicAuth
auth = HTTPBasicAuth()

@auth.get_password
def get_password(username):
if username == ‘miguel’:
return ‘python’
return None

@auth.error_handler
def unauthorized():
return make_response(jsonify(<'error': 'Unauthorized access'>), 401)

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

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


После настройки системы аутентификаци, осталось только добавить декоратор@auth.login_required для всех функций, которые должны быть защищены. Например:

@app.route(‘/todo/api/v1.0/tasks’, methods=[‘GET’])
@auth.login_required
def get_tasks():
return jsonify(<'tasks': tasks>)

Если мы попробуем запросить эту функцию с помощью curl мы получим примерно следующее:

$ curl -i http://localhost:5000/todo/api/v1.0/tasks
HTTP/1.0 401 UNAUTHORIZED
Content-Type: application/json
Content-Length: 36
WWW-Authenticate: Basic realm=»Authentication Required»
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Mon, 20 May 2013 06:41:14 GMT

<
«error»: «Unauthorized access»
>

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

$ curl -u miguel:python -i http://localhost:5000/todo/api/v1.0/tasks
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 316
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Mon, 20 May 2013 06:46:45 GMT

<
«tasks»: [
<
«title»: «Buy groceries»,
«done»: false,
«description»: «Milk, Cheese, Pizza, Fruit, Tylenol»,
«uri»: «http://localhost:5000/todo/api/v1.0/tasks/1»
>,
<
«title»: «Learn Python»,
«done»: false,
«description»: «Need to find a good Python tutorial on the web»,
«uri»: «http://localhost:5000/todo/api/v1.0/tasks/2»
>
]
>

Расширение с аутентификацией дает нам свободу выбирать какие функции будут в общем доступе, а какие защищены.

Для защиты регистрационной информации наш веб-сервис должен быть доступен через HTTP Secure server ( . ) который шифрует траффик между клиентом и сервером и предотвращает получение конфиденциальной информаци третьей стороной.

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

Простой путь обмануть браузер — возвращать любой другой код, вместо 401. Любимая всеми альтернатива это код 403, который означает ошибку «Forbidden». Хоть это достаточно близкая по смыслу ошибка, это нарушает стандарт HTTP, так что это неправильно. В частности будет хорошим решением не использовать веб-браузер в качестве клиентского приложения. Но в случаях, когда сервер и клиент разрабатываются совместно это спасает от многих неприятностей. Чтобы провернуть этот трюк нам нужно просто заменить код ошибки с 401 на 403:

@auth.error_handler
def unauthorized():
return make_response(jsonify(<'error': 'Unauthorized access'>), 403)

В клиентском приложении нужно тоже отлавливать ошибку 403.

Есть несколько возможностей улучшить разработанный нами сегодня веб-сервис.

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

Другой способ улучшить приложение это поддержка нескольких пользователей. Если система поддерживает несколько пользователей, то данные аутентификации могут использоваться чтобы возвращать персональные списки пользователям. В такой системе пользователи станут вторым ресурсом. Запрос POST будет регистрировать нового пользователя в системе. Запрос GET может возвращать информацию о пользователе. Запрос PUT может обновлять информацию о пользователе, например email. Запрос DELETE будет удалять пользователя из системы.

Запрос GET, который возвращает список задач, может быть расширен несколькими способами. Для начала это запрос может иметь опциональные агрументы, такие как количество задач на страницу. Другой путь сделать функцию более удобной это добавить критерии фильтрации. Например клиент может запросить только выполненые задачии или задачи, заголовок которых начинается с определенной буквы. Все эти элементы могут быть добавлены в URL как аргументы.

Законченый код для веб-сервиса To Do List вы можете взять здесь: https://gist.github.com/miguelgrinberg/5614326.

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

Я сделал 2 версии клиента для нашего сервиса:

Flask или Django? Выбираем Python вебфреймворк

Flask или Django?

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

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

Разница между Flask и Django

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

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

  • Объект Request — Flask использует локальные потоки, а Django передает запрос там, где это нужно.
  • Формы — Django доступен со встроенными формами, которые интегрируются с ORM и админкой сайта. Flask не поддерживает формы по умолчанию, но вы можете использовать WTForms, чтобы заполнить этот пробел.
  • Базы данных — Django доступен со встроенной ORM и системой миграции, которая может управлять базами данных. Flask не может этим похвастаться, однако есть инструменты, такие как SQLAlchemy, которые предоставляют аналогичный функционал (или даже больше).
  • Аутентификация и привилегии пользователям — Django предоставляет приложение аутентификации, которое предоставляет реализацию по умолчанию для пользовательского управления и привилегий. Flask предоставляет безопасные куки в качестве инструмента вашей собственной реализации.
  • Панель администратора — Django включает в себя полностью интегрированный админ-интерфейс для управления данными приложения. Flask не имеет таких функций, но Flask-Admin — очень популярное расширение, которое можно использовать для создания аналогичного административного инструмента.

Что такое Django?

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

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

Какие компании используют Django?

  • Instagram
  • Pinterest
  • Udemy
  • Coursera
  • Zapier

Что такое Flask?

На сайте Flask его описывают как “микрофреймворк для Python, основанный на Werkzeug, Jinja 2 и отличных решениях” и “веб-разработка, по капле за раз”. Еще раз, это дает вам хорошее представление о пространстве, которым Flask пытается заполнить переполненный мир веб-фреймворков Python.

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

Какие компании используют Flask

  • Netflix
  • Lyft
  • Reddit
  • Zillow
  • MailGun

Сходства и различия между Flask и Django

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

Среда разработки веб приложений на Python

Сервер разработки

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

Утилиты командной строки

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

Развертывание веб-приложения Flask с помощью uWSGI и Nginx на CentOS 6.4

Вступление

Появление Flask – одно из величайших событий в области разработки веб-приложений и фреймворков для Python за последние пару лет.

Популярный фреймворк Flask минималистичен и в то же время чрезвычайно функционален, расширяем и предоставляет огромный выбор сторонних библиотек (например, Flask-WTF или Flask-SQLAlchemy). Этот дружественный фреймворк – отличный способ начать разработку веб-приложений с помощью Python (особенно при необходимости ознакомиться со способами решения некоторых технических задач, что можно легко сделать благодаря простой и удобочитаемой базе исходных текстов).

Данное руководство описывает простые действия для развертывания и запуска приложений. Для начала нужно будет подготовить сервер развертывания для Python на CentOS 6.4, а также ознакомиться с работой сервера приложений uWSGI на основе инвертированного прокси-сервера Nginx.

Кратко о Flask

Учитывая характер Flask, почти все об этом фреймворке уже было сказано выше. По сути, это отлично спрограммированая минималистская библиотека разработки веб-приложений, требующая установки всего двух зависимостей: механизма шаблонов Jinja2 и инструментария Werkzeug WSGI.

При помощи Flask можно без труда создать структурированный веб-сайт, который растягивается из одного файла в десятки многоразовых модулей (т.е. компонентов).

Данное руководство использует самое основное, простейшее приложение Flask, специально созданное для демонстрации развертывания.

Развертывание веб-приложения

Что касается веб-приложений Python WSGI, их развертывание состоит из подготовки модуля WSGI, содержащего ссылку на объект приложения, что потом используется веб-сервером в качестве точки входа для передачи запросов, которые должны быть обработаны контроллерами приложений (или просмотров).

Здесь uWSGI выступает в качестве сервера приложений WSGI, который будет содержать приложение Flask, обслуживаемое Nginx. Поскольку Nginx имеет встроенную поддержку предпочитаемого и (как известно) быстрого протокола uWSGI, его нужно просто активировать.

Кратко о WSGI

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

Примечание: для получения дополнительной информации о WSGI и веб-серверах Python читайте статью «Сравнение веб-серверов для приложений на основе Python«.


В случае Flask операции WSGI обрабатываются базовой промежуточной библиотекой Werkzeug.

Nginx как инвертированный прокси-сервер

Nginx — это веб-сервер/инвертированный прокси очень высокой производительности.

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

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

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

Сервер веб-приложений Python WSGI

Серверы веб-приложений Python — это, как правило, либо написанные на языке C автономные серверы, либо полностью (или частично) основанные на Python серверы.

Они работают путем принятия модуля Python, который, как описано выше, содержит веб-приложение и обслуживает его в сети.

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

Популярные веб-серверы Python WSGI:

Кратко о uWSGI

Несмотря на очень запутанное соглашение об именах, сам uWSGI является обширным проектом, который состоит из большого количества компонентов и предоставляет полный набор программного обеспечения для построения хостинговых услуг. Один из этих компонентов, сервер uWSGI, запускает приложения Python WSGI.Он может использовать различные протоколы, в том числе свой ​​собственный идентичный SCGI протокол uwsgi. Поскольку HTTP-серверы по сравнению с серверами приложений более популярны, веб-серверы NGINX и Cherokee разработаны как модульные, что позволяет использовать собственный протокол uWSGI с высокой производительностью и обеспечивает прямой контроль над процессами.

  • Поставляется с адаптером WSGI и полностью поддерживает приложения Python на WSGI.
  • Связан с libpython. Он загружает код приложения при запуске и действует как интерпретатор Python, а также анализирует входящие запросы и вызывает Python.
  • Поставляется с прямой поддержкой популярного веб-сервера NGINX (а также Cherokee и Lighttpd).
  • Написан на языке C.
  • Различные компоненты могут сделать гораздо больше, чем просто запуск приложения, что может быть полезно для расширения функций.
  • В настоящее время (по состоянию на конец 2013 года), uWSGI активно развивается, регулярно появляются новые версии.
  • Имеет различные механизмы для запуска приложений (асинхронные и синхронные).
  • Невысокое потребление памяти при запуске.

Подготовка системы к развертыванию

Обновление системы

Чтобы сервер развертывания работал стабильно, очень важно использовать последние версии программ.

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

Чтобы обновить CentOS, запустите команду:

Установка Python, pip и virtualenv

Примечание: данное руководство действительно для версий CentOS 6.5, а также для 5.8 и 6.4.

По умолчанию CentOS / RHEL поставляется с минимальным количеством ПО. Набор необходимых инструментов на данном сервере предоставляется не для запуска приложений, а для питания инструментов системы (например, yum).

Чтобы подготовить систему CentOS, нужно установить (то есть, скомпилировать из исходного кода) Python, а затем установить pip и virtualenv при помощи специального интерпретатора.

В целом, для работы понадобятся следующие пакеты Python:

  • python-dev — средства разработки
  • pip— для управления пакетами
  • virtualenv— для создания изолированной виртуальной среды

Примечание: ниже приводится краткое (но весьма содержательное) изложение руководства «Установка Python 2.7.6 и 3.3.3 на CentOs 6.4«. Для получения более подробной информации о работе pip и virtualenv рекомендуется прочесть «Общие инструменты Python: использование virtualenv, установка пакетов с помощью pip и управление пакетами«.

Подготовка системы к разработке

Дистрибутивы CentOS намеренно поставляются без большинства необходимых приложений и инструментов.

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

Поэтому для начала нужно скачать и установить их.

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

Примечание: можно скачать несколько групп YUM одновременно.

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

yum groupinstall -y development

yum groupinstall -y ‘developmenttools’

Примечание: первая (более короткая) версия команды может не сработать на более старых дистрибутивах CentOS.

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

yum install -y zlib-developenssl-develsqlite-devel bzip2-devel

Загрузка, компилирование и установка Python на CentOS

Примечание: данные инструкции можно использовать для загрузки любой версии Python. Все, что нужно сделать — это указать нужную версию (в примере ниже — версия 2.7.6) . Можно установить и использовать несколько версий одновременно. В таком случае при запуске нужно будет указать версию (т.е. вместо python нужно использовать python2.7, python3.3, и т.д.).

Для начала нужно распаковать сжатый архив, содержащий исходный код Python. Данное руководство использует версию 2.7.6.

Этот файл сжимается с помощью библиотеки XZ. В зависимости от версии система может не иметь таковой. Если это так, выполните следующую команду, которая установит библиотеку XZ:

yum install xz-libs

Расшифруйте архив XZ, а затем извлеките содержимое tar-архива:

# Чтобы расшифровать (decode (-d)) архив tar:
xz -dPython-2.7.6.tar.xz
# Извлечь файлы:
tar -xvfPython-2.7.6.tar

Проверьте базу кода, используя ./configure:

# Откройте каталог с данным файлом:
cdPython-2.7.6
# Начните конфигурирование(задайте каталог установки)
# По умолчанию файлы устанавливаются в /usr/local.
# Отредактируйте —prefix,чтобы изменить это (например, на $HOME).
./configure —prefix=/usr/local

Соберите и установите Python 2.7.6:

# Скомпилируйте исходный код;
# Данная процедура может занять некоторое время (примерно несколько минут)
make && make altinstall

Дополнительно: добавление расположения новой установки Python в PATH:

Примечание: при использовании настроек по умолчанию выполнять это дополнительное действие нет необходимости. Однако, если при установке Python путь /usr/local был изменен, нужно будет выполнить следующие действия, чтобы иметь возможность запускать Python без указания полного пути.

# Синтаксис: export PATH=»[/путь/к/инсталляции]:$PATH»
export PATH=»/usr/local/bin:$PATH»

Чтобы узнать о PATH больше, обратитесь к информационному проекту Linux (Linux Information Project).

Установка общих инструментов Python: pip и virtualenv

Установив Python, нужно завершить формирование основы для производства и развертывания приложений. Для этого нужно установить наиболее часто используемые инструменты: менеджер пакетов pip и менеджер среды virtualenv.

Установка pip на CentOS при помощи новой инсталляции Python

Прежде чем устанавливать pip, нужно получить его единственную зависимость – setuptools.

Выполните следующие команды (для версии Python 2.7.6):

# Загрузите установочный файл с помощью wget:
wget —no-check-certificate https://pypi.python.org/packages/source/s/setuptools/setuptools-1.4.2.tar.gz
# Извлеките файлы из архива:
tar -xvf setuptools-1.4.2.tar.gz
# Перейдите в извлеченный каталог:
cd setuptools-1.4.2
# Установите setuptools при помощи Python (2.7.6)
python2.7 setup.py install

Сама по себе установка pip – очень простой процесс. Чтобы этот инструмент был автоматически загружен и установлен с помощью cUR Llibrary, используйте инструкции упомянутой выше стати.

Загрузите установочные файлы для pip и затем установите его с помощью Python (2.7):

curl https://raw.github.com/pypa/pip/master/contrib/get-pip.py | python2.7 —

Установка virtualenv на CentOS с помощью Python

Чтобы загрузить и установить virtualenv с помощью pip, запустите команду:

pip install virtualenv

Развертывание приложения

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

Создание каталога приложения для развертывания

Для начала соберите каталог приложения , содержащий:

  • модуль приложения;
  • каталог виртуальной среды;
  • необходимый серверу WSGI-файл.

# Folders / Directories
mkdir


/MyApplication # Replace the name to suit your needs
mkdir

/MyApplication/app # Application (module) directory
# Application Files
touch

/MyApplication/WSGI.py # Server entry-point
touch

/MyApplication/app/__init__.py # Application file

Создание виртуальной среды

Развернуть виртуальную среду очень просто.

Выполните следующее, чтобы инициировать новую среду внутри директории MyApplication:

Данная команда создаст новый каталог по имени env рядом с модулем приложения app.

Работа с виртуальной средой

Существует два способа использования виртуальной среды:

  • Активация среды
  • Установка местоположения интерпретатора Python внутри среды

Поскольку второй способ является более простым, явно укажите местоположения интерпретатора Python и pip.

Загрузка и установка uWSGI внутри виртуальной среды

Чтобы установить uWSGI с помощью pip, запустите:

/MyApplication/env/bin/pip install uwsgi

Это установит uWSGI внутри виртуальной среды.

Загрузка и установка библиотеки Flask

Чтобы установить Flask с помощью pip, запустите:

/MyApplication/env/bin/pip install flask

Создание примера приложения Flask

Для продолжения развертывания понадобится готовое к запуску приложение.

Создайте приложение Flask, состоящее из одной страницы.

Разместите ниже следующий контент, чтобы определить простое приложение:

from flask import Flask
app = Flask(__name__)
@app.route(«/»)
def hello():
return «Hello!»
if __name__ == «__main__»:
app.run()

Сохраните изменения и выйдите, нажав CTRL+X и Y для подтверждения.

Создание образца файла WSGI, импортирующего приложение

Обычно папка созданного приложения содержит основной модуль приложения (сведенный в один файл). Этот модуль приложения вместе с объектом приложения будут импортированы файлом WSGI для дальнейшей обработки. На данном этапе нужно создать файл WSGI, который будет импортировать приложение, и затем передать его на сервер приложений uWSGI.

Создайте (отредактируйте) файл WSGI.py:

Разместите в нем следующее:

from app import app
if __name__ == «__main__»:
app.run()

Стадия развертывания: установка и настройка Nginx

По описанным выше причинам, вне зависимости от выбранного сервера приложение CherryPy будет работать на Nginx. Итак прежде чем продолжить работу с серверами приложений, нужно загрузить и настроить Nginx.

Пример базовой архитектуры сервера:

Client Request — Nginx (Reverse-Proxy)
|
/|\
| | `-> App. Server I. 127.0.0.1:8080 # Our example
| ` App. Server II. 127.0.0.1:8082
`— App. Server III. 127.0.0.1:8083

Приведенные ниже инструкции недействительны для системы CentOS. При необходимости, пожалуйста, обратитесь к руководству «Как установить nginx на CentOS 6 с помощью yum».

Запустите следующую команду, чтобы установить Nginx с помощью aptitude:

# Активируйте репозиторий EPEL
sudosu -c ‘rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm’
# Загрузите и установите Nginx
sudo yum install -y nginx

Для запуска Nginx используйте:

sudo service nginx start

Чтобы выключить Nginx, используйте:

sudo service nginx stop

Чтобы перезапустить Nginx:

# Nginx нужно перезапускать после внесения любых изменений в настройки,
# чтобы новые настройки вступили в силу.
sudo service nginx restart

Настройка Nginx

Выбрав и установив веб-сервер для запуска приложения, нужно подготовить Nginx к работе с внутренним сервером (запускающим приложение WSGI).

Для этого нужно отредактировать конфигурационный файл nginx.conf.

Чтобы открыть и отредактировать данный файл с помощью текстового редактора nano, запустите:

sudo nano /etc/nginx/nginx.conf

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

Скоприуйте и вставьте приведенный ниже пример конфигураций.

Примечание: чтобы активировать поддрежку SSL, пожалуйста, прочтите статью «Создание SSL-сертификата на Nginx».

В приведенном ниже примере используется встроенная интеграцияNginx с сервером приложений uWSGI по протоколу uwsgi.

Пример конфигураций для веб-приложения:

worker_processes 1;
events <
worker_connections 1024;
>
http <
sendfile on;
gzip on;
gzip_http_version 1.0;
gzip_proxied any;
gzip_min_length 500;
gzip_disable «MSIE [1-6]\.»;
gzip_types text/plain text/xml text/css
text/comma-separated-values
text/javascript
application/x-javascript
application/atom+xml;
# Configuration containing list of application servers
upstream uwsgicluster <
server 127.0.0.1:8080;
# server 127.0.0.1:8081;
# ..
# .
>
# Configuration for Nginx
server <
# Running port
listen 80;
# Settings to by-pass for static files
location ^

/static/ <
# Example:
# root /full/path/to/application/static/file/dir;
root /app/static/;
>
# Serve a static file (ex. favico) outside static dir.
location = /favico.ico <
root /app/favico.ico;
>
# Proxying connections to application servers
location / <
include uwsgi_params;
uwsgi_passuwsgicluster;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
>
>
>

Отредактировав конфигурации, нажмите CTRL+X, чтобы выйти и сохранить изменения, и Y для подтверждения. Чтобы активировать внесенные изменения, нужно перезапустить Nginx.

Для этого введите:

sudo service nginx stop
sudo service nginx start

Установка сервера веб-приложения Python WSGI

Примечание: чтобы узнать о развертывании веб-приложений Python с помощью uWSGI больше, прочтите статью

Обслуживание приложений с помощью uWSGI

Данный раздел описывает работу веб-приложения PythonWSGIна сервере uWSGI. Как и другим серверам, серверу uWSGI нужно, чтобы приложение предоставило ему точки входа (т.е. объекты приложения). Во время запуска эти переменные конфигураций передаются серверу uWSGI и он начинает выполнять свою работу. При поступлении запроса uWSGI обрабатывает его, а затем передает его в контроллер приложения для обработки.

Запуск сервера

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

Примечание: прежде чем выполнить приведенные ниже команды, убедитесь, что каталог «my_app» является текущим, иначе uwsgi не сможет найти wsgi.py и не менее важный объект приложения.

Простой пример использования:

# Войдите в каталог приложения
cd

/MyApplication
# Запустите uWSGI, установленный внутри виртуальной среды
env/bin/uwsgi [option] [option 2] .. -w [wsgi file with app. callable]

Чтобы uWSGI начал обслуживать приложение из wsgi.py, запустите:

/MyApplication
env/bin/uwsgi —socket 127.0.0.1:8080 -w WSGI:app
# Чтобы uWSGI взаимодействовал с Nginx с помощью HTTP:
# env/bin/uwsgi —socket 127.0.0.1:8080 —protocol=http -w WSGI:app

Это запустит сервер в приоритетном режиме. Чтобы отключить его, нажмите клавиши CTRL + C.

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

env/bin/uwsgi —socket 127.0.0.1:8080 -w WSGI:app&


Запуская приложение в фоновом режиме, используйте менеджер процессов (например, htop), чтобы прервать его.

Готово! Подключив сервер приложения к Nginx, можете просмотреть его; для этого введите IP-адрес сервера в браузер.

http://[IP адрес сервера]/
# Hello, world!

Читайте также

Чтобы получить более подробную информацию о развертывании веб-приложений Python, читайте следующие статьи:

How do I unit test HTTP Digest Authentication in Flask?

I’ve got a flask app that implements a REST api. For reasons, I’m using HTTP Digest Authentication. I’ve used the Flask-HTTPAuth library to implement the digest authentication and it works; however, I am unable to authenticate in the unit tests.

For the unit tests, prior to setting up the authentication, I’m doing something like this:

Prior to implementing the authentication, this was fine. Now I get a 401, which is expected as the initial response for a digest auth request. I’ve searched and searched and followed a few suggestions related to http basic auth (using parameters data = < #various stuff>and follow_redirects=True) but I’ve had no success.

Does anyone have a clue how to implement unittests in this case?

Pipenv: руководство по новому инструменту Python

Все чаще во всевозможных статьях можно встретить использование pipenv вместо virualenv или workon. Если вы до сих пор не знаете что такое pipenv то это статья Alexander VanTol Pipenv: A Guide to the New Python Packaging Tool именно для вас.

Pipenv – это набирающий популярность пакет управления виртуальным окружением для Python, который решает некоторые распространенные проблемы, связанные с типичным рабочим процессом, в котором используется pip, virtualenv и старый добрый файл requirements.txt.

Как написано на официальном сайте: Pipenv – это инструмент, который призван привнести в мир Python лучшее из всех упаковочных миров (bundler, composer, npm, cargo, yarn и т. д.).

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

В этом руководстве мы рассмотрим, какие проблемы решает Pipenv и как управлять зависимостями Python с помощью Pipenv.

Какие проблемы решает Pipenv?

Для того чтобы понять преимущества Pipenv, нужно изучить текущие методы работы с пакетами и управления зависимостями в Python.

Давайте начнем с типичной ситуации в работе со сторонними пакетами. Затем мы рассмотрим пример развертывания приложения Python.

Управление зависимостями через requirements.txt

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

Таким образом, мы решаем включить зависимость от flask в файл requirements.txt:

Отлично, локально все работает, и после некоторого улучшения нашего приложения мы решили перенести его в продакшин. И вот тут все становится немного сложнее …

В приведенном выше файле requirements.txt нет указаний, какую версию flask нужно использовать. В этом случае pip install -r requirements.txt по умолчанию установит последнюю версию. Это нормально, если только в последней версии нет изменений интерфейса или поведения, которые нарушают наше приложение.

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

Теперь предположим, что мы развертываем свое приложение в рабочей среде и выполняете команду pip install -r requirements.txt. Pip инсталлирует последнюю, несовместимую с предыдущей версией версию flask, и именно так наше приложение выходит из строя ….

«Но эй, это работало на моей машине!» – я сам был, в такой ситуации много раз и это не очень приятное чувство.

На данный момент мы знаем, что версия flask, которую мы использовали во время разработки, работала нормально. Итак, чтобы исправить ситуацию, попытаемся быть немного более конкретным в наших требованиях в requirements.txt. Укажем конкретную версию flask. Это также называется “закреплением” (pinning a dependency) зависимости:

“Закрепление” зависимости flask к конкретной версии гарантирует, что install -r requirements.txt установит точную версию flask, которую мы использовали во время разработки. Но так ли это на самом деле?

Имейте в виду, что у самого flask также есть зависимости (которые устанавливаются автоматически). Тем не менее, сам flask не определяет точные версии для своих зависимостей. Например, он допускает любую версию Werkzeug >= 0.14.

Опять же, ради этого примера, допустим, была выпущена новая версия Werkzeug, и предположим что эта версия вызывает ошибку в нашем приложения.

На этот раз, когда мы выполним pip install -r requirements.txt в рабочей среде, получим flask == 0.12.1, так как мы закрепили это в нашем requirements.txt. Однако, к сожалению, мы так же получили самую последнюю версию Werkzeug которая вызывает у нас ошибку. Опять неожиданная проблема в другом окружение.

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

Типичным решением этой проблемы является использование pip freeze. Эта команда позволяет нам получить точные версии для всех сторонних библиотек, установленных в текущий момент времени, включая pip зависимостей, установленный автоматически. Таким образом, мы можем “заморозить” все зависимости в процессе разработки, чтобы обеспечить одинаковую среду в другом окружением.

Выполнение команды pip freeze приводит к “закреплению” зависимостей, которые мы можем добавить вручную в файл requirements.txt (или автоматически командой: pip freeze > requirements.txt ):

С помощью закрепления зависимостей мы можем быть уверены, что пакеты, установленные в нашей производственной среде, будут точно соответствовать пакетам в нашей среде разработки, чтобы ваш проект неожиданно не ломался. Это «решение», к сожалению, приводит к совершенно новому набору проблем.

Теперь, когда мы указали точные версии каждого стороннего пакета, мы несем ответственность за поддержание актуальности этих версий, даже несмотря на то, что они являются зависимыми компонентами flask. Что если в Werkzeug == 0.14.1 обнаружена дыра в безопасности, которую разработчики пакетов сразу же исправили в Werkzeug == 0.14.2 ? Теперь нам нужно обновиться до Werkzeug == 0.14.2, чтобы избежать каких-либо проблем безопасности, возникающих в более ранней версии.

Проблема в том что, мы должны как то узнать, что есть проблема с версией, которая у нас установлена. Затем нам нужно заняться установкой новой версию в нашей производственной среде самим. Но это не то что нам нужно. Правда в том, что нам действительно все равно, какая версия Werkzeug установлена у нас, если она не нарушает наш код. Мы не хотим на себя брать контроль над всеми зависимостями проекта. Нам нужно чтобы последнии версии зависимостей гарантировали, что мы автоматически получаем все необходимые исправления ошибок, исправления безопасности, новые функции, улучшенную оптимизации и так далее.

Реальный вопрос: «Как делать зависимости детерминированными для нашего проекта Python, не беря на себя ответственность за обновление версий?»

Спойлер: простой ответ – использование Pipenv.

Разработка проектов с разными зависимостями

Давайте немного переключимся, чтобы поговорить о другой распространенной проблеме, которая возникает, когда вы работаете над несколькими проектами. Представьте, что для ProjectA нужен django == 1.9, а для проекта ProjectB нужен django == 1.10.

По умолчанию Python пытается сохранить все наши сторонние пакеты в общесистемном расположении. Это означает, что каждый раз, когда мы хотим переключиться между ProjectA и ProjectB, мы должны убедиться, что установлена правильная версия django. Это делает переключение между проектами болезненным, потому что нужно удалить и переустановить пакеты, чтобы соответствовать требованиям для каждого проекта.

Стандартное решение заключается в использовании виртуальной среды, которая имеет собственный исполняемый файл Python и стороннее хранилище пакетов. Таким образом, ProjectA и ProjectB соответственно разделены. Теперь мы можем легко переключаться между проектами, поскольку они не используют одно и то же место хранения пакетов. PackageA может иметь любую версию django, которая ему нужна, в своей среде, а PackageB может иметь то, что ему нужно, совершенно отдельно. Самый распространенный инструмент для этого – virtualenv (или venv в Python 3).

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

Разрешение зависимостей

Что я имею в виду под разрешением зависимости? Допустим, у нас есть файл requirements.txt, который выглядит примерно так:

Допустим, для package_a есть подчиненная зависимость package_c, и для package_a требуется конкретная версия этого пакета: package_c > = 1.0. В свою очередь, package_b имеет ту же зависимость, но нуждается в package_c = 1.0 и = 1.0).

  • Затем pip устанавливает последнюю версию package_c, чтобы выполнить это требование. Допустим, последняя версия package_c == 3.1.
  • Но это и вызывает проблему. Если версия package_c, выбранная pip, не соответствует другим требованиям (например, package_b, нуждающемуся в package_c = 1.0,

    Начнем с установки:

    После того, как вы это сделали, вы можете фактически забыть о pip, поскольку Pipenv по сути выступает в качестве его замены. В нем также представлены два новых файла: Pipfile (который предназначен для замены requirements.txt) и Pipfile.lock (который отвечает за детерминированность сборки).

    Pipenv использует pip и virtualenv под капотом, что упрощает их использование с помощью одного интерфейса командной строки.

    Пример использования

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

    Эта команда создаст виртуальную среду. Pipenv для создания виртуальных сред использует путь по умолчанию. Если вы хотите изменить это поведение в Pipenv, для настройки есть переменные среды.

    Вы можете принудительно создать среду Python 2 или 3 с аргументами –two и –three соответственно. В противном случае, Pipenv будет использовать то, что найдет по умолчанию virtualenv.

    Если требуется более конкретная версия Python, вы можете использовать аргумент –python с нужной версией.

    Теперь можно установить сторонний пакет, который нам нужен. Стоп, но мы то знаем, что нам нужна версия 0.12.1, а не последняя версия, так что давай установим именно ее:

    Мы должны увидеть что-то вроде следующего в терминале:

    Обратите внимание, что создаются два файла, Pipfile и Pipfile.lock. Мы рассмотрим их подробнее через секунду. Давайте установим еще один сторонний пакет, numpy. Нам не нужна конкретная версия, поэтому версию указывать не будем:

    Если вы хотите установить что-то непосредственно из системы контроля версий (VCS), то это тоже можно сделать! Нужно указать местоположения аналогично тому, как вы это делаете с помощью pip. Например, чтобы установить библиотеку requests из системы управления версиями, выполните следующую команду:

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

    Использование аргумента –dev поместит зависимость в специальную папку [dev-packages] в Pipfile. Зависимости размещенной в этой папке будут устанавливаются только в том случае, если вы укажете аргумент –dev в pipenv install. Это позволит отделить зависимости, необходимые только для разработки, от зависимостей, необходимых для фактической работы базового кода. Ранее это можно было сделать с помощью дополнительных файлов requirements, таких как dev-requirements.txt или test-requirements.txt. Теперь все объединено в один Pip-файл с разными разделами.

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

    Эта команда создаст/обновит файл Pipfile.lock, который вам никогда не придется (и никогда не нужно) редактировать вручную. Вы всегда должны использовать только сгенерированный файл.

    Теперь, нам нужно перенести свой код проекта в рабочую среду включая файлы Pipfile и Pipfile.lock . Далее создать там собственную среду окружения командой pipenv shell. И далее установить все зависимости командой:

    –ignore-pipfile говорит Pipenv игнорировать Pipfile для установки и использовать то, что находится в Pipfile.lock. Учитывая Pipfile.lock, Pipenv создаст ту же среду, которая была у нас, когда мы запустили блокировку зависимостей в pipenv.

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

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

    Эта команда установит все зависимости, необходимые для разработки, которые включают в себя как обычные зависимости, так и те, которые вы указали в аргументе –dev во время установки.

    Если в файле Pipfile не указывается точная версия, команда install устанавливает последние версии зависимостей.


    Это важное замечание, потому что оно решает некоторые из предыдущих проблем, которые мы обсуждали. Для демонстрации, допустим, вышла новая версия одной из наших зависимостей. Поскольку нам не нужна конкретная версия этой зависимости, мы не указываем точную версию в Pipfile. При pipenv install новая версия зависимости будет установлена автоматически.

    Теперь мы как бы вносим изменения в код и запускаем несколько тестов, чтобы убедиться, что все по-прежнему работает должным образом. (У нас есть юнит-тесты, верно?) Теперь, как и раньше, мы блокируете свою среду с помощью pipenv lock, и с новой версией зависимости будет сгенерирован обновленный файл Pipfile.lock. Как и раньше, мы можем скопировать этот файл вместе с другими в другую среду и там запустить pipenv install , если необходимо .

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

    Подход к разрешению зависимостей Pipenv

    Pipenv попытается установить подчиненные зависимости, которые удовлетворяют всем требованиям основных зависимостей. Однако, если существуют конфликтующие зависимости (package_a требуется package_c> = 1.0, а package_b требуется package_c

    Кроме того, допустим, вы хотите полностью стереть все установленные пакеты из вашей виртуальной среды:

    Вы можете заменить –all на –all-dev, чтобы просто удалить пакеты dev.

    Pipenv поддерживает автоматическую загрузку переменных среды, когда в каталоге верхнего уровня существует файл .env. Таким образом, когда вы запускаете pipenv shell для открытия виртуальной среды, она загружает переменные среды из этого файла.

    Файл .env должен просто содержат пары ключ-значение:

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

    Команда что бы узнать, по какому пути находится виртуальная среда:

    Команда что бы узнать, по какому пути находится ваш проект:

    Что делать если у меня уже есть requirements.txt. Как его с конвертировать в Pipfile e ?

    Если вы запускаете pipenv install, он должен автоматически определить наличия файла requirements.txt и преобразовать его в файл Pipfile, выдав похожее сообщение:

    Обратите внимание на приведенное выше предупреждение.

    Если вы указали точные версии в вашем файле requirements.txt, вы, вероятно, захотите изменить свой Pipfile, указав только те версии, которые вам действительно нужны. Это позволит вам получить все преимущества от перехода на Pipenv. Например, допустим, у вас есть следующая зависимость, но вам не нужна точная версия numpy:

    Если у вас нет особых требований к версии ваших зависимостей, вы можете использовать подстановочный знак *, чтобы сообщить Pipenv, что можно установить любую версию:

    Если вы опасаетесь использовать любую версию *, обычно лучше указывать текущую версию, в которой вы уже находитесь, или более старшую:

    Вы также можете установить зависимости из файла requirements.txt вручную используя аргумент -r:

    Если у вас есть файл dev-requirements.txt или что-то подобное, вы также можете добавить их в Pipfile. Просто добавьте аргумент –dev, чтобы он был помещен в правильный раздел:

    Кроме того, вы можете пойти другим путем и сгенерировать файлы requirements.txt из Pipfile:

    Стоит ли использовать Pipenv?

    Определенно. Даже если это просто способ объединить инструменты, которые вы уже используете (pip & virtualenv), в единый интерфейс. Тем не менее, это гораздо больше, чем просто объеденение. Используя Pipfile вы указываете только те зависимости, которые вам действительно нужны.

    У вас больше не будет головной боли, от того что вам нужно было самим управлять версиями всего лишь для того, чтобы убедиться, что вы можете клонировать свою среду разработки. С Pipfile.lock вы можете работать над своим проектом со спокойной душой, зная, что вы можете точно воспроизвести свое окружение в любом месте.

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

    Создание веб-приложения с использованием Python Flask и MySQL

    Russian (Pусский) translation by Yuri Yuriev (you can also view the original English article)

    В этой серии мы будем использовать Python, Flask и MySQL для создания простого веб-приложения с нуля. Это будет приложение списка дел, в котором пользователи смогут зарегистрироваться, подписаться и создать свой список желаний.

    Предполагается, что у вас есть базовые знания языка программирования Python . Мы будем использовать Flask , инфраструктуру веб-приложений Python для создания приложения и MySQL как сервер.

    Введение в Python Flask

    Flask — это фреймворк Python для создания веб-приложений. С официального сайта,

    Flask — это микрофреймворк для Python на основе Werkzeug, Jinja 2 и благих намерений.

    Когда мы думаем о Python, первое, что приходит нам в голову, — это Django framework. Но с точки зрения новичка в Python, начинать с Flask легче, чем с Django.

    Установка Flask

    Установить Flask легко и просто. С менеджером пакетов pip нужно сделать только:

    Когда вы закончите установку Flask, создайте папку FlaskApp . Перейдите в папку FlaskApp и создайте файл с именем app.py . Импортируйте модуль flask и создайте приложение с помощью Flask, как показано ниже:

    Теперь определим основной путь / и соответствующий ему обработчик запросов:

    Затем проверьте, является ли исполняемый файл главной программой и запустите приложение:

    Сохраните изменения и выполните app.py :

    Укажите браузеру на http://localhost:5000/ и у вас должно появиться приветственное сообщение.

    Создание домашней страницы

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

    Flask ищет файлы шаблонов внутри папки templates . Перейдите в папку PythonApp и создайте папку под названием templates . Внутри templates создайте файл index.html . Откройте index.html и пропишите следующий HTML:

    Откройте app.py и импортируйте render_template , который мы будем использовать для рендеринга файлов шаблонов.

    Измените основной метод, чтобы вернуть созданный файл шаблона.

    Сохраните изменения и перезапустите сервер. Указав браузеру http://localhost:5000/ вы увидите следующее:

    Создание страницы регистрации

    Шаг 1. Настройка базы данных

    Мы будем использовать MySQL в качестве сервера. Войдите в MySQL из командной строки или, если вы предпочитаете GUI, например, MySQL work bench, тоже можете пользоваться. Сначала создайте базу данных BucketList . Из командной строки:

    Введите требуемый пароль и при входе в систему выполните следующую команду для создания базы данных:

    Как только база данных будет создана, создайте таблицу tbl_user , как показано ниже:

    Мы будем использовать Stored procedures в приложении Python для взаимодействия с базой данных MySQL. Поскольку таблица tbl_user была создана, создайте процедуру сохранения под названием sp_createUser , чтобы зарегистрировать пользователя.

    При создании этой процедуры в таблице tbl_user сначала нужно проверить, не существует ли пользователь с тем же именем username . Если существует, нам нужно выдать ошибку, иначе мы создадим пользователя в таблице user. Вот как должна выглядеть процедура sp_createUser :

    Шаг 2. Создание интерфейса регистрации

    Перейдите в каталог PythonApp/templates и создайте файл HTML с именем signup.html . Добавьте следующий код HTML в signup.html :

    Добавьте такой CSS как signup.css в постоянную папку внутри PythonApp .

    В app.py добавьте метод showSignUp для отображения страницы регистрации после поступления запроса в /showSignUp :

    Сохраните изменения и перезапустите сервер. Нажмите кнопку Sign Up на главной странице и у вас должна получиться такая страница регистрации:

    Шаг 3. Внедрение метода регистрации

    Затем нам нужен server-s >PythonApp и откройте app.py . Создайте новый метод signUp , а также добавьте /signUp . Так это выглядит:

    Мы будем использовать jQuery AJAX для публикации данных регистрации в методе signUp , поэтому укажем метод в определении маршрута.

    Чтобы прочитать опубликованные значения, нам нужно импортировать request из Flask.

    С помощью request мы прочитаем значения, как показано ниже:

    Как только значения прочитаны, мы проверяем, верны ли они, а пока давайте вернём простое сообщение:

    Импортируйте json из Flask, так как мы используем его для возвращения данных json .

    Шаг 4. Создание запроса на регистрацию

    Мы будем использовать jQuery AJAX для отправки запроса на регистрацию в метод Python. Загрузите jQuery , разместите его внутри PythonApp/static/js и добавьте ссылку на него со страницы регистрации. Как только jQuery будет включен, мы добавим запрос POST JQuery при нажатии кнопки Sign Up .

    Итак, давайте присоединим событие нажатия кнопки, как показано:

    Сохраните изменения и перезапустите сервер. На странице Sign Up заполните данные и нажмите Sign Up. Проверьте браузер, у вас должно получиться следующее сообщение:

    Шаг 5: вызов хранимой процедуры MySQL

    У нас есть name , email address и password , мы вызываем процедуру MySQL для создания нового пользователя.

    Чтобы соединиться с MySQL, мы будем использовать Flask-MySQL, который является расширением Flask. Чтобы начать работу с Flask-MySQL , установите его с помощью менеджера пакетов pip :

    Импортируйте MySQL внутрь app.py :

    Ранее мы определили наше приложение:


    Наряду с этим, включая следующие конфигурации MySQL:

    Сначала давайте создадим соединение MySQL:

    Когда соединение установлено, нам понадобится cursor для запроса stored процедуры. Через conn соединение создаём курсор.

    Перед вызовом stored процедуры, давайте сделаем надёжный пароль с помощником от Werkzeug. Импортируйте модуль в app.py :

    Используйте модуль для создания хэшированного пароля.

    Теперь вызываем процедуру sp_createUser :

    Если процедура выполнена успешно, мы зафиксируем изменения и вернем сообщение об успешном завершении.

    Сохраните изменения и перезапустите сервер. На странице регистрации введите name , email address и password и нажмите кнопку Sign Up. После успешного создания пользователя вы увидите сообщение в консоли браузера.

    Подводя итоги

    В этом уроке мы рассмотрели начало работы по созданию приложения с помощью Python Flask , MySQL и расширения Flask-MySQL . Мы создали и прописали таблицы базы данных, stored процедуру, а также обеспечили функциональность регистрации. В следующем уроке мы перейдём на уровень выше, реализовав функции входа в систему и некоторые ещё.

    Исходный код к этому уроку доступен на GitHub.

    Пишем одностраничное приложение с Flask и Vue.js

    Эта статья — пошаговое руководство по настройке базового CRUD-приложения с помощью Vue и Flask. Начнём с создания нового приложения Vue, используя Vue CLI, а затем перейдём к выполнению основных операций CRUD с помощью RESTful API на бэкенде под управлением Python и Flask.

    К концу этого урока вы узнаете:

    • что такое Flask;
    • что такое Vue и как он соотносится с другими UI-библиотеками и фронтенд-фреймворками вроде Angular и React.
    • выстраивать Vue-проект, используя Vue CLI;
    • создавать и рендерить компоненты Vue в браузере;
    • создавать одностраничные приложения с компонентами Vue;
    • подключать Vue-приложение к бэкенду Flask;
    • разрабатывать RESTful API с помощью Flask;
    • стилизовать компоненты Vue с помощью Bootstrap;
    • использовать Vue Router для создания маршрутов и рендеринга компонентов.

    Что такое Flask?

    Flask — это простой, но мощный микро-фреймворк для Python, идеально подходящий для создания RESTful API. Как Sinatra (Ruby) и Express (Node), он минималистичен и гибок, поэтому вы можете начинать с простых проектов и при необходимости создавать более сложные приложения.

    Если вы первый раз работаете с Flask, вам стоит изучить следующие ресурсы:

    Что такое Vue?

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

    15–16 ноября, Минск, 133–390 br

    Чтобы узнать больше о Vue, а также о плюсах и минусах его использования по сравнению с Angular и React, можете посмотреть следующие статьи:

    Если вы первый раз работаете с Vue, вам следует прочитать введение из официального руководства Vue.

    Настройка Flask

    Начнём с создания новой директории проекта:

    В директории flask-vue-crud создайте новый каталог с именем server . Затем в этом каталоге создайте и активируйте виртуальную среду разработки:

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

    Установите Flask вместе с расширением Flask-CORS:

    Добавьте файл app.py в только что созданный каталог:

    Flask-CORS нужен для отправки cross-origin-запросов (запросы, исходящие из другого протокола, IP-адреса, имени домена или порта), поэтому необходимо включить общий доступ к ресурсам (CORS).

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

    Для проверки введите в строку адреса браузера http://localhost:5000/ping. Должно получиться: « Pong! ».

    Нажмите Ctrl + C , чтобы завершить работу сервера. Затем вернитесь к корневой папке проекта. Теперь перейдём к фронтенду и настроим Vue.

    Настройка Vue

    Для создания индивидуального темплейта проекта используем мощный интерфейс Vue CLI.

    Установите его глобально:

    Если вы первый раз работаете с npm, вам будет полезно почитать официальное руководство по нему.

    В каталоге flask-vue-crud выполните следующую команду для инициализации нового проекта Vue под именем client с конфигом webpack:

    webpack — это пакетный модуль и инструмент для сборки, используемый для создания, минимизации и объединения файлов JavaScript и других клиентских ресурсов.

    Шаги создания нового проекта Vue:

    1. Vue-сборка: Runtime + Compiler.
    2. Установить vue-router? — Да.
    3. Использовать ESLint для линтинга кода? — Да.
    4. Выберите пресет ESLint — Airbnb.
    5. Настроить юнит-тесты? — Нет.
    6. Настроить тесты e2e с Nightwatch? — Нет.
    7. Запустить установку npm после создания проекта? — Да, использовать NPM.

    Должно получиться следующее:

    Обратите внимание на сгенерированную структуру проекта. Она может показаться большой, но по факту вы будете иметь дело только с файлами и папками в каталоге /src вместе с файлом index.html .

    Файл index.html является отправной точкой данного Vue-приложения.

    Также обратите внимание на элемент

    Файлы и каталоги внутри папки src :

    main.js — точка входа в приложение, которая загружает и инициализирует Vue вместе с корневым компонентом.
    App.vue — корневой компонент, из которого будут рендериться все остальные компоненты (отправная точка).
    assets — место хранения статических ассетов вроде изображений и шрифтов.
    components — место хранения UI-компонентов.
    router — место определения URL-адресов и сопоставление их с компонентами.

    Взгляните на файл client/src/components/HelloWorld.vue . Это компонент Single File, который разбит на три разных подраздела:

    • template: для компонентного HTML;
    • script: здесь компонентная логика реализована через JavaScript;
    • style: для стилей CSS.

    Перейдите по адресу http://localhost:8080 в браузере. Вы должны увидеть следующее:

    Добавьте новый компонент с именем Ping.vue в папку client/src/components :

    Обновите файл client/src/router/index.js так, чтобы он отображал / в компонент Ping:

    В client/src/App.vue удалите изображение из темплейта:

    Теперь в браузере должно отобразиться « Hello! ».

    Чтобы соединить клиентское Vue-приложение с бэкендом на Flask, можно использовать библиотеку axios для отправки AJAX-запросов.

    Начнём с установки:

    Обновим раздел script компонента в Ping.vue следующим образом:

    Запустите приложение Flask в новом окне. В браузере по адресу http://localhost:8080 должно отобразиться « pong! ». По сути, после ответа от серверной части устанавливаем в msg значение, полученное из data вернувшегося объекта.

    Настройка Bootstrap

    Добавим Bootstrap, чтобы можно было быстро настроить стиль приложения.

    Игнорируйте предупреждения для jquery и popper.js . Не добавляйте их в свой проект.

    Импортируем стили Bootstrap в client/src/main.js :

    Обновим раздел style в client/src/App.vue :

    Убедитесь, что Bootstrap подключён корректно, используя Button и Container в компоненте Ping :

    Добавим компонент Books в новый файл Books.vue :

    Для избавления от хеша в URL замените mode на history , чтобы использовать history API браузера для навигации:

    Добавим таблицу в стиле Bootstrap в компонент Books :

    Отображаться должно следующее:

    Теперь можно приступить к созданию функциональности CRUD-приложения.


    Что будем создавать?

    Цель — разработать бэкенд RESTful API, работающий на Python и Flask, для единственного ресурса — книги. API должен следовать принципам разработки RESTful, используя основные HTTP-команды: GET, POST, PUT и DELETE.

    GET-маршрут

    Сервер

    Добавим список книг в server/app.py :

    Добавим обработчик маршрута:

    Теперь запустим приложение и проверим маршрут по адресу http://localhost:5000/books.

    Клиент

    После инициализации компонента вызываем метод getBooks() через хук жизненного цикла (lifecycle hook) created, который выбирает книги из только что настроенного маршрута на бэкенде.

    Больше информации про Lifecycle Hook находится здесь.

    В темплейте просматривается список книг с помощью директивы v-for, которая создаёт новую строку таблицы на каждой итерации. Значение индекса используется в качестве ключа (key). Затем используется директива v-if для отображения Yes или No — читал пользователь книгу или нет.

    Bootstrap Vue

    В следующем разделе используем компонент Modal для добавления новых книг. Для этого добавим библиотеку Bootstrap Vue, которая предоставляет набор Vue-компонентов, стилизованных с помощью HTML и CSS на основе Bootstrap.

    Выбор Bootstrap Vue обоснован тем, что компонент Modal Bootstrap использует jQuery. Следует избегать совместного использования jQuery и Vue в одном проекте, поскольку последний использует Virtual Dom для обновления DOM-структуры. Другими словами, если вы используете jQuery для манипуляций с DOM, Vue об этом не узнает. По крайней мере, если вам необходимо использовать jQuery, не используйте его вместе с Vue на одних и тех же элементах DOM.

    Подключим библиотеку Bootstrap Vue в файле client/src/main.js :

    POST-маршрут

    Сервер

    Обновим существующий обработчик маршрута для обработки POST-запросов для добавления новых книг:

    Запустив сервер Flask, вы можете проверить POST-маршрут на новой вкладке браузера:

    Вы также должны увидеть добавленную книгу по http://localhost:5000/books.

    Клиент

    Внесём следующий modal для добавления новой книги. Начнём с HTML:

    Эту часть нужно добавить непосредственно перед закрывающим тегом

    Что делает Hide-Footer , вы можете просмотреть самостоятельно в документации по Bootstrap Vue.

    Обновим раздел script :

    Рассмотрим, что происходит в этом фрагменте кода.

    1. addBookForm() привязывается к входным данным формы через v-model . Это называется двусторонней привязкой. Узнать об этом подробнее вы можете здесь.
    2. onSubmit() запускается, когда пользователь успешно отправляет форму. При отправке предотвращается обычное поведение браузера ( evt.preventDefault() ), закрывается modal ( this.$Refs.addBookModal.hide() ), запускается метод addBook() и очищается форма ( initForm() ).
    3. addBook() отправляет POST-запрос в /books для добавления новой книги.
    4. Остальные изменения вы можете посмотреть самостоятельно в документации Vue по мере необходимости.

    Теперь обновим кнопку «Add Book» в темплейте, чтобы при её нажатии отображался modal:

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

    Можно выполнить проверку, попробовав добавить книгу.

    Компонент Alert

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

    Добавим новый файл с именем Alert.vue в каталог client/src/components :

    Затем импортируем его в разделе script компонента Books и зарегистрируем:

    Теперь можно ссылаться на новый компонент в разделе template :

    Обновите браузер. Должно быть отображено следующее:

    Теперь добавим фактический компонент b-alert в шаблон:

    Обратите внимание на параметр props в разделе script . Можно передавать сообщение из родительского компонента ( Books ) следующим образом:

    Больше информации о props находится здесь.

    Чтобы сделать Alert динамическим и передать пользовательское сообщение, можно использовать выражение привязки (binding expression) в Books.vue :

    Добавьте message в параметр data в Books.vue :

    Обновим сообщение в addBook :

    Добавим v-if , чтобы alert отображался, только если showMessage имеет значение true :

    Добавим showMessage в data :

    Снова обновим addBook() , установив в showMessage значение true :

    Теперь можно проверить работу.

    PUT-маршрут

    Сервер

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

    Обновим BOOKS в server/app.py :

    Также не забудьте импортировать:

    Рефакторинг all_books для учёта уникального идентификатора при добавлении новой книги:

    Добавим новый обработчик маршрута:

    Добавим вспомогательную функцию:

    Клиент

    Будем идти пошагово:

    1. Добавление modal и формы.
    2. Обработка нажатия кнопки Update.
    3. Подключение AJAX-запроса.
    4. Оповещение пользователя (Alert).
    5. Обработка нажатия кнопки Cancel.

    1. Добавление modal и формы

    Сначала добавим новый modal к темплейту, сразу после первого modal:

    Добавим стейт формы в часть data раздела script :

    2. Обработка нажатия кнопки Update

    Обновим кнопку «Update» в таблице:

    Добавим новый метод для обновления значений в editForm :

    Затем добавим метод, обрабатывающий отправку формы:

    3. Подключение AJAX-запроса

    4. Оповещение пользователя (Alert)

    5. Обработка нажатия кнопки Cancel

    Обязательно протестируйте приложение. Убедитесь, что modal отображается при нажатии кнопки и что введённые значения заполнены правильно.

    DELETE-маршрут

    Сервер

    Обновим обработчик маршрута:

    Клиент


    Обновим кнопку «Delete» следующим образом:

    Добавим методы для обработки нажатия кнопки, а затем удалим книгу:

    Когда пользователь нажимает кнопку удаления, вызывается метод onDeleteBook() , который запускает другой метод removeBook() . Этот метод отправляет DELETE-запрос на сервер. Когда приходит ответ, отображается Alert и запускается getBooks() .

    Заключение

    В этой статье были рассмотрены основы настройки CRUD-приложения с помощью Vue и Flask. Исходный код из тега v1 вы можете найти в репозитории flask-vue-crud.

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

    Рвётесь в бой? Эта страница даёт хорошее введение в Flask. Предполагается, что вы уже имеете установленный Flask. Если это не так, обратитесь к секции Инсталляция .

    Минимальное приложение¶

    Минимальное приложение Flask выглядит примерно так:

    Просто сохраните его под именем наподобие hello.py и запустите с помощью вашего интерпретатора Python. Только, пожалуйста, не давайте приложению имя flask.py , так как это вызовет конфликт с самим Flask.

    Проследовав по ссылке http://127.0.0.1:5000/ вы увидите ваше приветствие миру.

    Итак, что же делает этот код?

    1. Сначала мы импортировали класс Flask . Экземпляр этого класса и будет вашим WSGI-приложением.
    2. Далее мы создаём экземпляр этого класса. Первый аргумент — это имя модуля или пакета приложения. Если вы используете единственный модуль (как в этом примере), вам следует использовать __name__ , потому что в зависимости от того, запущен ли код как приложение, или был импортирован как модуль, это имя будет разным ( ‘__main__’ или актуальное имя импортированного модуля соответственно). Это нужно, чтобы Flask знал, где искать шаблоны, статические файлы и прочее. Для дополнительной информации, смотрите документацию Flask .
    3. Далее, мы используем декоратор route() , чтобы сказать Flask, какой из URL должен запускать нашу функцию.
    4. Функция, которой дано имя, используемое также для генерации URL-адресов для этой конкретной функции, возвращает сообщение, которое мы хотим отобразить в браузере пользователя.
    5. Наконец, для запуска локального сервера с нашим приложением, мы используем функцию run() . Благодаря конструкции if __name__ == ‘__main__’ можно быть уверенным, что сервер запустится только при непосредственном вызове скрипта из интерпретатора Python, а не при его импортировании в качестве модуля.

    Для остановки сервера, нажмите Ctrl+C.

    Публично доступный сервер

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

    Если у вас отключена опция debug или вы доверяете пользователям в сети, вы можете сделать сервер публично доступным, просто изменив вызов метода run() таким вот образом:

    Это укажет вашей операционной системе, чтобы она слушала сеть со всех публичных IP-адресов.

    Режим отладки¶

    Метод run() чудесно подходит для запуска локального сервера для разработки, но вы будете должны перезапускать его всякий раз при изменении вашего кода. Это не очень здорово, и Flask здесь может облегчить жизнь. Если вы включаете поддержку отладки, сервер перезагрузит сам себя при изменении кода, кроме того, если что-то пойдёт не так, это обеспечит вас полезным отладчиком.

    Существует два способа включить отладку. Или установите флаг в объекте приложения:

    Или передайте его как параметр при запуске:

    Оба метода вызовут одинаковый эффект.

    Несмотря на то, что интерактивный отладчик не работает в многопоточных окружениях (что делает его практически неспособным к использованию на реальных рабочих серверах), тем не менее, он позволяет выполнение произвольного кода. Это делает его главной угрозой безопасности, и поэтому он никогда не должен использоваться на реальных «боевых» серверах.

    Снимок экрана с отладчиком в действии:

    Предполагаете использовать другой отладчик? Тогда смотрите Работа с отладчиками .

    Маршрутизация¶

    Современные веб-приложения используют «красивые» URL. Это помогает людям запомнить эти URL, это особенно удобно для приложений, используемых с мобильных устройств с более медленным сетевым соединением. Если пользователь может перейти сразу на желаемую страницу, без предварительного посещения начальной страницы, он с большей вероятностью вернётся на эту страницу и в следующий раз.

    Как вы увидели ранее, декоратор route() используется для привязки функции к URL. Вот простейшие примеры:

    Но это еще не все! Вы можете сделать определенные части URL динамически меняющимися и задействовать в функции несколько правил.

    Правила для переменной части¶

    Чтобы добавлять к адресу URL переменные части, можно эти особые части выделить как . Затем подобные части передаются в вашу функцию в качестве аргумента — в виде ключевого слова. Также может быть использован конвертер — с помощью задания правила следующего вида . Вот несколько интересных примеров

    Существуют следующие конвертеры:

    int принимаются целочисленные значения
    float как и int , только значения с плавающей точкой
    path подобно поведению по умолчанию, но допускаются слэши

    Уникальные URL / Перенаправления

    Правила для URL, работающие в Flask, основаны на модуле маршрутизации Werkzeug. Этот модуль реализован в соответствие с идеей обеспечения красивых и уникальных URL-адресов на основе исторически попавшего в обиход — из поведения Apache и более ранних HTTP серверов.

    Возьмём два правила:

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

    Однако, во втором случае, URL определен без косой черты — как путь к файлу на UNIX-подобных системах. Доступ к URL с завершающей косой чертой будет приводить к появлению ошибки 404 «Not Found».

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

    Построение (генерация) URL¶

    Раз Flask может искать соответствия в URL, может ли он их генерировать? Конечно, да. Для построения URL для специфической функции, вы можете использовать функцию url_for() . В качестве первого аргумента она принимает имя функции, кроме того она принимает ряд именованных аргументов, каждый из которых соответствует переменной части правила для URL. Неизвестные переменные части добавляются к URL в качестве параметров запроса. Вот некоторые примеры:

    (Здесь также использован метод test_request_context() , который будет объяснён ниже. Он просит Flask вести себя так, как будто он обрабатывает запрос, даже если мы взаимодействуем с ним через оболочку Python. Взгляните на нижеследующее объяснение. Локальные объекты контекста (context locals) .

    Зачем Вам может потребоваться формировать URL-ы с помощью функции их обращения url_for() вместо того, чтобы жёстко задать их в ваших шаблонах? Для этого есть три веские причины:

    1. По сравнению с жёстким заданием URL внутри кода обратный порядок часто является более наглядным. Более того, он позволяет менять URL за один шаг, и забыть про необходимость изменять URL повсюду. 2. Построение URL будет прозрачно для вас осуществлять экранирование специальных символов и данных Unicode, так что вам не придётся отдельно иметь с ними дела. 3. Если ваше приложение размещено не в корневой папке URL root (а, скажем, в /myapplication вместо / ), данную ситуацию нужным для вас образом обработает функция url_for() .

    Методы HTTP¶

    HTTP (протокол, на котором общаются веб-приложения) может использовать различные методы для доступа к URL-адресам. По умолчанию, route отвечает лишь на запросы типа GET , но это можно изменить, снабдив декоратор route() аргументом methods . Вот некоторые примеры:

    Если присутствует метод GET , то автоматически будет добавлен и HEAD . Вам не придётся иметь с ним дело. Также, при этом можно быть уверенным, что запросы HEAD будут обработаны в соответствии с требованиями HTTP RFC (документ с описанием протокола HTTP), так что вам не требуется ничего знать об этой части спецификации HTTP. Кроме того, начиная с Flask версии 0.6, для вас будет автоматически реализован метод OPTIONS автоматически.

    Не имеете понятия, что такое метод HTTP? Не беспокойтесь, здесь приводится быстрое введение в методы HTTP, и почему они важны:

    HTTP-метод (также часто называемый командой) сообщает серверу, что хочет сделать клиент с запрашиваемой страницей. Очень распространены Следующие методы:

    GET Браузер говорит серверу, чтобы он просто получил информацию, хранимую на этой странице, и отослал её. Возможно, это самый распространённый метод. HEAD Браузер просит сервер получить информацию, но его интересует только заголовки, а не содержимое страницы. Приложение предполагает обработать их так же, как если бы был получен запрос GET , но без доставки фактического содержимого. В Flask, вам вовсе не требуется иметь дело с этим методом, так как нижележащая библиотека Werkzeug сделает всё за вас. POST Браузер говорит серверу, что он хочет сообщить этому URL некоторую новую информацию, и что сервер должен убедиться, что данные сохранены и сохранены в единожды. Обычно, аналогичным образом происходит передача из HTML форм на сервер данных. PUT Похоже на POST , только сервер может вызвать процедуру сохранения несколько раз, перезаписывая старые значения более одного раза. Здесь вы можете спросить, зачем это нужно, и есть несколько веских причин, чтобы делать это подобным образом. Предположим, во время передачи произошла потеря соединения: в этой ситуации система между браузером и сервером, ничего не нарушая, может совершенно спокойно получить запрос во второй раз. С POST такое было бы невозможно, потому что он может быть вызван только один раз. DELETE Удалить информацию, расположенную в указанном месте. OPTIONS Обеспечивает быстрый способ выяснения клиентом поддерживаемых для данного URL методов. Начиная с Flask 0.6, это работает для вас автоматически.

    Теперь самое интересное: в HTML 4 и XHTML1, единственными методами, которыми форма может отправить серверу данные, являются GET и POST . Но для JavaScript и будущих стандартов HTML вы также можете использовать и другие методы. Кроме того, в последнее время HTTP стал довольно популярным, и теперь браузеры уже не единственные клиенты, использующие HTTP. Например, его используют многие системы контроля версий.

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

    Динамические веб-приложения также нуждаются и в статических файлах. Обычно, именно из них берутся файлы CSS и JavaScript. В идеале ваш веб-сервер уже сконфигурирован так, чтобы обслуживать их для вас, однако в ходе разработке это также может делать и сам Flask. Просто создайте внутри вашего пакета или модуля папку с названием static , и она будет доступна из приложения как /static .

    Чтобы сформировать для статических файлов URL, используйте специальное окончание ‘static’ :

    Этот файл должен храниться в файловой системе как static/style.css .

    Визуализация шаблонов¶

    Генерация HTML из Python — невесёлое и на самом деле довольно сложное занятие, так как вам необходимо самостоятельно заботиться о безопасности приложения, производя для HTML обработку специальных последовательностей (escaping). Поэтому внутри Flask уже автоматически преднастроен шаблонизатор Jinja2.

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

    Flask будет искать шаблоны в папке templates . Поэтому, если ваше приложение выполнено в виде модуля, эта папка будет рядом с модулем, а если в виде пакета, она будет внутри вашего пакета:

    Первый случай — модуль:

    Второй случай — пакет:

    При работе с шаблонами вы можете использовать всю мощь Jinja2. За дополнительной информацией обратитесь к официальной Документации по шаблонам Jinja2

    Вот пример шаблона:

    Также, внутри шаблонов вы имеете доступ к объектам request , session и g [1], а также к функции get_flashed_messages() .

    Шаблоны особенно полезны при использовании наследования. Если вам интересно, как это работает, обратитесь к документации по заготовкам Template Inheritance . Проще говоря, наследование шаблонов позволяет разместить определённые элементы (такие, как заголовки, элементы навигации и «подвал» страницы) на каждой странице.

    Автоматическая обработка специальных (escape-) последовательностей (escaping) включена по умолчанию, поэтому если name содержит HTML, он будет экранирован автоматически. Если вы можете доверять переменной и знаете, что в ней будет безопасный HTML (например, потому что он пришёл из модуля конвертирования разметки wiki в HTML), вы можете пометить её в шаблоне, как безопасную — с использованием класса Markup или фильтра |safe . За дополнительными примерами обратитесь к документации по Jinja2.

    Вот основные возможности по работе с классом Markup :

    Изменено в версии 0.5: Автоматическая обработка escape-последовательностей больше не активирована для всех шаблонов. Вот расширения шаблонов, которые активизируют автообработку: .html , .htm , .xml , .xhtml . Шаблоны, загруженные из строк, не будут обрабатывать специальные последовательности.

    [1] Затрудняетесь понять, что это за объект — g ? Это то, в чём вы можете хранить информацию для ваших собственных нужд, для дополнительной информации смотрите документацию на этот объект ( g ) и sqlite3 .

    Доступ к данным запроса¶

    Для веб-приложений важно, чтобы они реагировали на данные, которые клиент отправляет серверу. В Flask эта информация предоставляется глобальным объектом request . Если у вас есть некоторый опыт по работе с Python, вас может удивить, как этот объект может быть глобальным, и как Flask при этом умудрился остаться ориентированным на многопоточное выполнение.

    Локальные объекты контекста (context locals)¶


    Информация от инсайдера

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

    Некоторые объекты в Flask являются глобальными, но необычного типа. Эти объекты фактически являются прокси (посредниками) к объектам, локальным для конкретного контекста. Труднопроизносимо. Но на самом деле довольно легко понять.

    Представьте себе контекст, обрабатывающий поток. Приходит запрос, и веб-сервер решает породить новый поток (или нечто иное — базовый объект может иметь дело с системой параллельного выполнения не на базе потоков). Когда Flask начинает осуществлять свою внутреннюю обработку запроса, он выясняет, что текущий поток является активным контекстом и связывает текущее приложение и окружение WSGI с этим контекстом (потоком). Он делает это с умом — так, что одно приложение может, не ломаясь, вызывать другое приложение.

    Итак, что это означает для вас? В принципе, вы можете полностью игнорировать, что это так, если вы не делаете чего-либо вроде тестирования модулей. Вы заметите, что код, зависящий от объекта запроса, неожиданно будет работать неправильно, так как отсутствует объект запроса. Решением является самостоятельное создание объекта запроса и его привязка к контексту. Простейшим решением для тестирования модулей является использование менеджера контекстов test_request_context() . В сочетании с оператором with этот менеджер свяжет тестовый запрос так, что вы сможете с ним взаимодействовать. Вот пример:

    Другая возможность — это передача целого окружения WSGI методу request_context() method:

    Объект запроса¶

    Объект запроса документирован в секции API, мы не будем рассматривать его здесь подробно (смотри request ). Вот широкий взгляд на некоторые наиболее распространённые операции. Прежде всего, вам необходимо импортировать его из модуля flask :

    В настоящее время метод запроса доступен через использование атрибута method . Для доступа к данным формы (данным, которые передаются в запросах типа POST или PUT ), вы можете использовать атрибут form . Вот полноценный пример работы с двумя упомянутыми выше атрибутами:

    Что произойдёт, если ключ, указанный в атрибуте form , не существует? В этом случае будет возбуждена специальная ошибка KeyError . Вы можете перехватить её подобно стандартной KeyError , но если вы этого не сделаете, вместо этого будет показана страница с ошибкой HTTP 400 Bad Request . Так что во многих ситуациях вам не придётся иметь дело с этой проблемой.

    Для доступа к параметрам, представленным в URL ( ?ключ=значение ), вы можете использовать атрибут args :

    Мы рекомендуем доступ к параметрам внутри URL через get или через перехват KeyError , так как пользователь может изменить URL, а предъявление ему страницы с ошибкой 400 bad request не является дружественным.

    За полным списком методов и атрибутов объекта запроса, обратитесь к следующей документации: request .

    Загрузка файлов на сервер¶

    В Flask обработка загружаемых на сервер файлов является несложным занятием. Просто убедитесь, что вы в вашей HTML-форме не забыли установить атрибут enctype=»multipart/form-data» , в противном случае браузер вообще не передаст файл.

    Загруженные на сервер файлы сохраняются в памяти или во временной папке внутри файловой системы. Вы можете получить к ним доступ, через атрибут объекта запроса files . Каждый загруженный файл сохраняется в этом словаре. Он ведёт себя так же, как стандартный объект Python file , однако он также имеет метод save() , который вам позволяет сохранить данный файл внутрь файловой системы сервера. Вот простой пример, показывающий, как это работает:

    Если вы хотите до загрузки файла в приложение узнать, как он назван на стороне клиента, вы можете просмотреть атрибут filename . Однако, имейте в виду, что данному значению никогда не стоит доверять, потому что оно может быть подделано. Если вы хотите использовать имя файла на клиентской стороне для сохранения файла на сервере, пропустите его через функцию secure_filename() , которой вас снабдил Werkzeug:

    Некоторые более удачные примеры можно найти в разделе заготовок: Загрузка файлов .

    Cookies¶

    Для доступа к cookies можно использовать атрибут cookies . Для установки cookies можно использовать метод объектов ответа set_cookie . Атрибут объектов запроса cookies — это словарь со всеми cookies, которые передаёт клиент. Если вы хотите использовать сессии, то не используйте cookies напрямую, вместо этого используйте во Flask Сессии , который при работе с cookies даст вам некоторую дополнительную безопасность.

    Заметьте, что cookies устанавливаются в объектах ответа. Так как вы обычно просто возвращаете строки из функций представления, Flask конвертирует их для вас в объекты ответа. Если вы это хотите сделать явно, то можете использовать функцию, make_response() , затем изменив её.

    Иногда вы можете захотеть установить cookie в точке, где объект ответа ещё не существует. Это можно сделать, используя заготовку deferred-callbacks .

    Также об этом можно почитать здесь: Об ответах .

    Ошибки и перенаправления¶

    Чтобы перенаправить пользователя в иную конечную точку, используйте функцию redirect() ; для того, чтобы преждевременно прервать запрос с кодом ошибки, используйте функцию abort() function:

    Это довольно бессмысленный пример, потому что пользователь будет перенаправлен с индексной страницы на страницу, на которую у него нет доступа ( 401 означает отказ в доступе), однако он показывает, как это работает.

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

    Обратите внимание на 404 после вызова render_template() . Это сообщит Flask, что код статуса для этой страницы должен быть 404, что означает «не найдено». По умолчанию предполагается код «200», который означает «всё прошло хорошо».

    Об ответах¶

    Возвращаемое из функции представления значение автоматически для вас конвертируется вас в объект ответа. Если возвращаемое значение является строкой, оно конвертируется в объект ответа в строку в виде тела ответа, код статуса 200 OK и в mimetype со значением text/html . Логика, которую применяет Flask для конвертации возвращаемых значений в объекты ответа следующая:

    1. Если возвращается объект ответа корректного типа, он прямо возвращается из представления.
    2. Если это строка, создаётся объект ответа с этими же данными и параметрами по умолчанию.
    3. Если возвращается кортеж, его элементы могут предоставлять дополнительную информацию. Такие кортежи должны соответствовать форме (ответ, статус, заголовки) , кортеж должен содержать хотя бы один из перечисленных элементов. Значение статус заменит код статуса, а элемент заголовки может быть или списком или словарём с дополнительными значениями заголовка.
    4. Если ничего из перечисленного не совпало, Flask предполагает, что возвращаемое значение — это допустимая WSGI-заявка, и конвертирует его в объект ответа.

    Если вы хотите в результате ответа заполучить объект внутри представления, то можете использовать функцию make_response() .

    Представим, что вы имеете подобное представление:

    Вам надо всего лишь обернуть возвращаемое выражение функцией make_response() и получить объект ответа для его модификации, а затем вернуть его:

    Сессии¶

    В дополнение к объекту ответа есть ещё один объект, называемый session , который позволяет вам сохранять от одного запроса к другому информацию, специфичную для пользователя. Это реализовано для вас поверх cookies, при этом используется криптографическая подпись этих cookie. Это означает, что пользователь может посмотреть на содержимое cookie, но не может ничего в ней изменить, если он конечно не знает значение секретного ключа, использованного для создания подписи.

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

    Упомянутая escape() осуществляет для вас обработку специальных последовательностей (escaping), что необходимо, если вы не используете движок шаблонов (как в этом примере).

    Как генерировать хорошие секретные ключи

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

    Просто возьмите, скопируйте/вставьте это в ваш код, вот и готово.

    Замечание о сессиях на базе cookie: Flask возьмёт значения, которые вы помещаете в объект сессии, и сериализует их в cookie. Если вы обнаружили какие-либо значения, которые не сохраняются между запросами, а cookies реально включены, а никаких ясных сообщений об ошибках не было, проверьте размер cookie в ответах вашей страницы и сравните с размером, поддерживаемым веб-браузером.

    Message Flashing¶

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

    Чтобы вызвать всплывающие сообщения, используйте метод flash() , чтобы заполучить сообщения, можно использовать метод, также доступный для шаблонов — get_flashed_messages() . Полный пример приведён в разделе Всплывающие сообщения .

    Ведение журналов¶

    Добавлено в версии 0.3.

    Иногда может возникнуть ситуация, в которой вы имеете дело с данными, которые должны быть корректными, но в действительности это не так. К примеру, у вас может быть некий код клиентской стороны, который посылает HTTP-запрос к серверу, однако он очевидным образом неверен. Это может произойти из-за манипуляции пользователя с данными, или из-за неудачной работы клиентского кода. В большинстве случаев ответом, адекватным ситуации будет 400 Bad Request , но иногда, когда надо, чтобы код продолжал работать, это не годится.

    Вы по-прежнему хотите иметь журнал того, что пошло не так. Вот где могут пригодиться объекты создания журнала logger . Начиная с Flask 0.3, инструмент для журналирования уже настроен для использования.

    Вот некоторые примеры вызовов функции журналирования:

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

    Как зацепиться (hooking) к промежуточному слою WSGI¶

    Если вы хотите добавить в ваше приложение слой промежуточного, или связующего для WSGI программного обеспечения (middleware), вы можете обернуть внутреннее WSGI-приложение. К примеру, если вы хотите использовать одно из middleware из пакета Werkzeug для обхода известных багов в lighttpd, вы можете сделать это подобным образом:

    Развёртывание приложения на веб-сервере¶

    Готовы к развёртыванию на сервере вашего нового приложения Flask? В завершение краткого руководства, вы можете немедленно развернуть приложение на одной из платформ хостинга, предоставляющих бесплатное размещение для малых проектов:

    Другие места, где можно разместить ваше приложение:

    Если вы управляете собственными хостами и желаете разместиться у себя, смотрите раздел Варианты развёртывания .

    Simple Login Extension for Flask

    There are good and recommended options to deal with web authentication in Flask.

    I recommend you use:

    Those extensions are really complete and production ready!

    So why Flask Simple Login?

    However sometimes you need something simple for that small project or for prototyping.

    Flask Simple Login

    What it provides:

    • Login and Logout forms and pages
    • Function to check if user is logged-in
    • Decorator for views
    • Easy and customizable login_checker

    What it does not provide: (but of course you can easily implement by your own)

    • Database Integration
    • Password management
    • API authentication
    • Role or user based access control

    Hot it works

    First install it from PyPI.

    That’s it! now you have /login and /logout routes in your application.

    The username defaults to admin and the password defaults to secret (yeah that’s not clever, let’s see how to change it)

    Configuring

    That works, but is not so clever, lets use env vars.

    then SimpleLogin will read those env vars automatically.

    But what if you have more users and more complex auth logic? write a custom login checker

    Using a custom login checker

    Checking if user is logged in

    Decorating your views

    Protecting Flask Admin views

    Customizing templates

    There are only one template to customize and it is called login.html

    And you can customize it in anyway you want and need, it receives a form in context and it is a WTF form the submit should be done to request.path which is the same /login view.

    You can also use <% if is_logged_in %>in your template if needed.

    Мастер Йода рекомендует:  Защищаем Perl
    Добавить комментарий