Что такое flask в python
Быстрый старт¶
Минимальное приложение¶
Минимальное приложение Flask выглядит примерно так:
Проследовав по ссылке http://127.0.0.1:5000/ вы увидите ваше приветствие миру.
Итак, что же делает этот код?
Для остановки сервера, нажмите Ctrl+C.
Публично доступный сервер
Если вы запустите сервер, вы заметите, что он доступен только с вашего собственного компьютера, а не с какого-либо другого в сети. Так сделано по умолчанию, потому что в режиме отладки пользователь приложения может выполнить код на Python на вашем компьютере.
Если у вас отключена опция debug или вы доверяете пользователям в сети, вы можете сделать сервер публично доступным, просто изменив вызов метода run() таким вот образом:
Это укажет вашей операционной системе, чтобы она слушала сеть со всех публичных IP-адресов.
Режим отладки¶
Метод run() чудесно подходит для запуска локального сервера для разработки, но вы будете должны перезапускать его всякий раз при изменении вашего кода. Это не очень здорово, и Flask здесь может облегчить жизнь. Если вы включаете поддержку отладки, сервер перезагрузит сам себя при изменении кода, кроме того, если что-то пойдёт не так, это обеспечит вас полезным отладчиком.
Существует два способа включить отладку. Или установите флаг в объекте приложения:
Или передайте его как параметр при запуске:
Оба метода вызовут одинаковый эффект.
Несмотря на то, что интерактивный отладчик не работает в многопоточных окружениях (что делает его практически неспособным к использованию на реальных рабочих серверах), тем не менее, он позволяет выполнение произвольного кода. Это делает его главной угрозой безопасности, и поэтому он никогда не должен использоваться на реальных «боевых» серверах.
Снимок экрана с отладчиком в действии:
Маршрутизация¶
Современные веб-приложения используют «красивые» URL. Это помогает людям запомнить эти URL, это особенно удобно для приложений, используемых с мобильных устройств с более медленным сетевым соединением. Если пользователь может перейти сразу на желаемую страницу, без предварительного посещения начальной страницы, он с большей вероятностью вернётся на эту страницу и в следующий раз.
Как вы увидели ранее, декоратор route() используется для привязки функции к URL. Вот простейшие примеры:
Но это еще не все! Вы можете сделать определенные части URL динамически меняющимися и задействовать в функции несколько правил.
Правила для переменной части¶
Существуют следующие конвертеры:
Уникальные URL / Перенаправления
Возьмём два правила:
Хоть они и выглядят довольно похожими, есть разница в использовании слэша в определении URL. В первом случае, канонический URL имеет завершающую часть projects со слэшем в конце. В этом смысле он похож на папку в файловой системе. В данном случае, при доступе к URL без слэша, Flask перенаправит к каноническому URL с завершающим слэшем.
Построение (генерация) URL¶
Зачем Вам может потребоваться формировать URL-ы с помощью функции их обращения url_for() вместо того, чтобы жёстко задать их в ваших шаблонах? Для этого есть три веские причины:
Методы HTTP¶
Не имеете понятия, что такое метод HTTP? Не беспокойтесь, здесь приводится быстрое введение в методы HTTP, и почему они важны:
HTTP-метод (также часто называемый командой) сообщает серверу, что хочет сделать клиент с запрашиваемой страницей. Очень распространены Следующие методы:
Статические файлы¶
Чтобы сформировать для статических файлов URL, используйте специальное окончание ‘static’ :
Визуализация шаблонов¶
При работе с шаблонами вы можете использовать всю мощь Jinja2. За дополнительной информацией обратитесь к официальной Документации по шаблонам Jinja2
Вот пример шаблона:
Вот основные возможности по работе с классом Markup :
Доступ к данным запроса¶
Локальные объекты контекста (context locals)¶
Информация от инсайдера
Прочтите этот раздел, если вы хотите понять, как это работает, и как вы можете реализовать тесты с локальными переменными контекста. Если вам это неважно, просто пропустите его.
Некоторые объекты в Flask являются глобальными, но необычного типа. Эти объекты фактически являются прокси (посредниками) к объектам, локальным для конкретного контекста. Труднопроизносимо. Но на самом деле довольно легко понять.
Объект запроса¶
Объект запроса документирован в секции API, мы не будем рассматривать его здесь подробно (смотри request ). Вот широкий взгляд на некоторые наиболее распространённые операции. Прежде всего, вам необходимо импортировать его из модуля flask :
Загрузка файлов на сервер¶
Cookies¶
Ошибки и перенаправления¶
Чтобы перенаправить пользователя в иную конечную точку, используйте функцию redirect() ; для того, чтобы преждевременно прервать запрос с кодом ошибки, используйте функцию abort() function:
Это довольно бессмысленный пример, потому что пользователь будет перенаправлен с индексной страницы на страницу, на которую у него нет доступа ( 401 означает отказ в доступе), однако он показывает, как это работает.
По умолчанию, для каждого кода ошибки отображается чёрно-белая страница с ошибкой. Если вы хотите видоизменить страницу с ошибкой, то можете использовать декоратор errorhandler() :
Об ответах¶
Представим, что вы имеете подобное представление:
Вам надо всего лишь обернуть возвращаемое выражение функцией make_response() и получить объект ответа для его модификации, а затем вернуть его:
Сессии¶
В случае использования сессий вам необходимо установить значение этого секретного ключа. Вот как работают сессии:
Упомянутая escape() осуществляет для вас обработку специальных последовательностей (escaping), что необходимо, если вы не используете движок шаблонов (как в этом примере).
Как генерировать хорошие секретные ключи
Проблемой случайных значений является то, что трудно сказать, что действительно является является случайным. А секретный ключ должен быть настолько случайным, насколько это возможно. У вашей операционной системы есть способы для генерации достаточно случайных значений на базе криптографического случайного генератора, который может быть использован для получения таких ключей:
Просто возьмите, скопируйте/вставьте это в ваш код, вот и готово.
Замечание о сессиях на базе cookie: Flask возьмёт значения, которые вы помещаете в объект сессии, и сериализует их в cookie. Если вы обнаружили какие-либо значения, которые не сохраняются между запросами, а cookies реально включены, а никаких ясных сообщений об ошибках не было, проверьте размер cookie в ответах вашей страницы и сравните с размером, поддерживаемым веб-браузером.
Message Flashing¶
Хорошие приложения и интерфейсы пользователя дают обратную связь. Если пользователь не получает достаточной обратной связи, вскоре он может начать ненавидеть приложение. При помощи системы всплывающих сообщений Flask предоставляет пользователю по-настоящему простой способ обратной связи. Система всплывающих сообщений обычно делает возможным записать сообщение в конце запроса и получить к нему доступ во время обработки следующего и только следующего запроса. Обычно эти сообщения используются в шаблонах макетов страниц, которые его и отображают.
Ведение журналов¶
Добавлено в версии 0.3.
Вот некоторые примеры вызовов функции журналирования:
Как зацепиться (hooking) к промежуточному слою WSGI¶
Если вы хотите добавить в ваше приложение слой промежуточного, или связующего для WSGI программного обеспечения (middleware), вы можете обернуть внутреннее WSGI-приложение. К примеру, если вы хотите использовать одно из middleware из пакета Werkzeug для обхода известных багов в lighttpd, вы можете сделать это подобным образом:
Развёртывание приложения на веб-сервере¶
Готовы к развёртыванию на сервере вашего нового приложения Flask? В завершение краткого руководства, вы можете немедленно развернуть приложение на одной из платформ хостинга, предоставляющих бесплатное размещение для малых проектов:
Другие места, где можно разместить ваше приложение:
Flask
Flask является микрофреймворком для создания вебсайтов на языке Python. В основу статьи положен перевод из официальной документации Flask. Поэтому в ней имеется обращение от первого лица, то есть от создателя фреймворка Армина Ронахера.
Flask в данном контексте переводится как пороховой рожок, на это указывает официальное лого.
Содержание
Предисловие [ править ]
Что значит «микро»? [ править ]
На мой взгляд «микро» в фреймворке относится не только к простоте и небольшому размеру базы, но это также может означать тот факт, что он не предлагает вам много проектных решений. Несмотря на то, что Flask использует нечто подобное в виде шаблонизатора, мы не будем принимать подобные решения для вашего хранилища данных или других частей. Тем не менее, для нас термин «микро» не означает, что вся реализация должна вписываться в один файл.
Одним из проектных решений во Flask является то, что простые задачи должны быть простыми; они не должны занимать много кода, и это не должно ограничивать вас. Поэтому мы сделали несколько вариантов дизайна, некоторые люди могут посчитать это удивительным и даже странным. Например, Flask использует локальные треды внутри объектов, так что вы не должны передавать объекты в пределах одного запроса от функции к функции, оставаясь в безопасном треде. Хоть это и очень простой подход, который позволяет сэкономить время, такое решение может вызвать некоторые проблемы для слишком больших приложений, поскольку изменения в этих локальных тредах-объектах могут произойти где угодно в этом треде. Для того, чтобы решить эти проблемы, мы не стали скрывать от вас локальные треды-объекты, вместо этого мы охватываем их и предоставляем вам много инструментов, чтобы сделать работу с ними настолько приятной, насколько это возможно.
Во Flask многие вещи предварительно сконфигурированы, на основе общей базовой конфигурации. Например, шаблоны и статические файлы сохранены в подкаталогах в пределах исходного дерева. Вы также можете изменить это, но обычно этого не требуется.
Основная причина почему Flask называется «микрофреймворком» — это идея сохранить ядро простым, но расширяемым. В нем нет абстрактного уровня базы данных, нет валидации форм или всего того, что уже есть в других библиотеках. Однако, Flask поддерживает расширения, которые могут добавить необходимую функциональность и имплементирует их так, как будто они уже были встроены изначально. В настоящее время уже есть расширения: формы валидации, поддержка закачки файлов, различные технологии аутентификации и многие другие.
Безопасность [ править ]
Статус насчет Python 3 [ править ]
Werkzeug и Flask поддерживают Python 3.
Установка [ править ]
Имеются две зависимости:
Jinja2 — движок темплейтов
Werkzeug — набор инструментов WSGI, стандартного интерфейса Python для развертывания веб-приложений и взаимодействия между ними и различными серверами разработки.
Virtualenv — не является зависимостью. Это инструмент, который призван решить проблему обратной совместимости. Вы можете использовать различные версии Python или версии библиотек, это может вызвать конфликт зависимостей. Virtualenv решает эту проблему, создает изолированную среду для каждого проекта.
Под Windows [ править ]
Запустить командную строку cmd
Проще всего установить при помощи скрипта easy_install. В командной строке должно получиться что-то вроде этого:
C:\Python27\python.exe C:\Python27\Scripts\easy_install-2.7-script.py Flask
Установка зависимостей:
C:\Python27\python.exe C:\Python27\Scripts\easy_install-2.7-script.py Jinja2
C:\Python27\python.exe C:\Python27\Scripts\easy_install-2.7-script.py Werkzeug
C:\Python27\python.exe C:\Python27\Scripts\easy_install-2.7-script.py Virtualenv
Установка под Linux [ править ]
В терминале написать pip install flask
Краткая документация [ править ]
Простейший Hello world [ править ]
Создадим файл hello.py следующего содержания:
Проверим как установился Flask. Запустим скрипт:
C:\Python27\python.exe hello.py
Наберите в браузере в адресной строке http://localhost:5000/ и увидите надпись Hello World!
В версии Flask 1.0.2 процесс запуска изменился. Требуется следующая команда:
FLASK_APP=hello.py flask run
Не забудьте, для запуска сначала требуется перейти в консоли в папку, где хранится скрипт.
Разбор программы Hello world! [ править ]
Рассмотрим, как работает программа, которую вы запустили выше:
Общедоступный сервер [ править ]
Если вы запустите сервер, вы заметите, что он доступен только с вашего компьютера, а не с любого другого компьютера в сети. Это значение выставлено по умолчанию, потому что в режиме отладки пользователь приложения может выполнить произвольный код на вашем компьютере.
Если вы доверяете пользователям в вашей сети, вы можете сделать сервер общедоступным, просто изменив вызов run(), который должен выглядеть следующим образом:
Это говорит вашей операционной системе слушать на всех ip (интерфейсах).
Режим отладки [ править ]
Метод run() хорош для начала разработки на локальном сервере. Но это потребует ручного перезапуска сервера после каждого изменения в коде. Хорошо что Flask может справиться с этой проблемой. Если включить Debug Mode, сервер будет сам перегружаться после каждого изменения в коде. Еще вы получите полезный отладчик, на тот случай если что-то пойдет не так.
Есть два способа включить режим отладки:
app.debug = True
app.run()
Или
app.run(debug=True)
Оба метода дадут одинаковый эффект
Внимание
Несмотря на то, что интерактивный отладчик не работает в разветвленной среде (что делает его практически невозможным в использовании на производственных серверах), он все же позволяет выполнить произвольный код. Это делает его одним из основных рисков в безопасности, и поэтому он никогда не должен быть использован на производственных машинах.
Маршрутизация [ править ]
Современные веб-приложения имеют красивые URL. Это помогает людям помнить их, особенно это удобно для приложений, которые используются в мобильных устройствах с медленным сетевым подключением. Если пользователь может попасть на страницу через URL минуя главную страницу, то более вероятно, что он вернется в следующий раз.
Как вы видели выше, декоратор route() используется для связывания функций с URL. Вот несколько основных примеров:
Но это еще не все! Вы можете сделать некоторые части URL динамическими и применить несколько правил к функции.
Использование переменных [ править ]
Имеются следующие конверторы
int | Принимает целые числа |
float | то же самое, что int, только с плавающей точкой |
path | похоже на то, что установлено по умолчанию, но принимает слэши |
Уникальные линки и редирект [ править ]
Линки во Flask основаны на базе модуля маршрутизации от Werkzeug. Идея этого модуля заключается в обеспечении красивых и уникальных URL-адресов на основе правил ранее сформировавшихся в Apache и в HTTP серверах.
Используйте два правила:
Хоть эти примеры и выглядят очень похоже, они различаются по слэшу в конце URL. В первом случае, доступ без слэша вызывает редирект на канонические URL с обратным слэшем.
Во втором случае, без обратного слэша, URL определяется, как путь к файлу на UNIX-подобных системах. Доступ к URL со слэшем будет перенаправляться на ошибку 404 «не найдено».
Такое поведение позволяет пользователям получить доступ к странице, даже если они забыли ввести в конце обратный слэш. Кроме того, URL-адрес будет оставаться уникальным, и это поможет поисковым системам избегать повторного индексирования страницы.
Генерация URL [ править ]
Здесь также используется метод test_request_context(), который объяснен ниже. Он говорит Flask, как нужно обрабатывать запрос, даже если мы взаимодействуем через шел Python. Почему мы используем построение URL вместо их жесткого задания в шаблонах? На то есть три хорошие причины:
HTTP методы [ править ]
HTTP (мы говорим о протоколе веб-приложения) знает различные способы доступа к URL-адресам. По умолчанию маршрут реагирует только на ответы GET-запросов, но это можно изменить путем предоставления методов, используя аргументы к декоратору route(). Вот несколько примеров:
Если присутствует GET, тогда HEAD будет добавлен автоматически. Вам не нужно об этом заботиться. Также будьте уверены, что HEAD поддерживает HTTP RFC зависимости, так что вы можете полностью игнорировать HTTP спецификации.
Если вы ничего не знаете про HTTP методы, приводим небольшую справку:
Браузер сообщает серверу, что желает получить информацию со страницы и просит отправить ее. Возможно, это самый распространенный метод.
Браузер сообщает серверу, что желает получить информацию, но интересуется только заголовком, а не содержанием страницы. Приложение допускает запрос, в случае если GET был получен.
Браузер сообщает серверу, что хочет запостить новую информацию по данному URL и сервер должен быть уверен, что сохранит ее и сделает один раз. Так обычно передается информация из HTML форм на сервер.
Очень схоже с POST, но сервер может инициировать сохранение информации несколько раз, переписывая старые значения более одного раза. Вы можете задаться вопросом: «Для чего это нужно?». Есть несколько хороших причин, чтобы делать это таким образом. Учтите, что соединение может быть потеряно во время передачи: в этой ситуации система между браузером и сервером может затребовать передачу во второй раз. С POST это невозможно, так как запрос возможен только один раз.
Удаление информации в полученной локации.
Быстрый способ для клиента выяснить какой из методов поддерживается по данному URL. Начиная с Flask 0.6 эта возможность имплементирована автоматически.
Самое интересное в том, что HTML4 и XHTML1 поддерживают методы GET и POST. Но с использованием JavaScript и будущих стандартов HTML можно использовать другие методы. Кроме того HTTP стал весьма популярным в последнее время и браузеры — уже не единственные клиенты, использующие протокол HTTP. Например, многие системы контроля версий используют его.
Статические файлы [ править ]
Динамическим веб-приложениям также требуются статические файлы. Обычно это css и javascript файлы. В идеале, ваш веб-сервер уже настроен, чтобы их обслуживать, но если вам потребуется, вы можете изменить настройки во Flask. Просто создайте папку с названием static в вашем пакете или рядом с модулем и она будет доступна в /static по применению.
Для генерации адресов для статических файлов, используйте специальное имя ‘static’:
Файл будет доступен в файловой системе по пути static/style.css
Рендеринг шаблонов [ править ]
Создание HTML из Python — это не удовольствие, а громоздкий процесс. Так как HTML обладает своей свободой, вы должны озаботиться безопасностью своего приложения. В связи с этим Flask автоматически настраивает для нас Jinja2 (механизм шаблонов).
Чтобы создать шаблон, можно использовать метод render_template(). Все, что вам нужно сделать, — это указать имя шаблона и переменные, которые вы хотите передать в шаблоны как ключевые аргументы. Вот простой пример того, как сделать шаблон:
Flask будет искать шаблоны в папке шаблонов. Таким образом, если ваше приложение представляет собой модуль, эта папка находится рядом с этим модулем, если же это пакет, то на самом деле внутри вашего пакета:
Случай с модулем:
Внутри шаблонов, вы также имеете доступ к реквестам, сессиям и g-объектам, а также можете использовать get_flashed_messages() функцию. G-объекты, имеется ввиду, если вам необходимо сохранить информацию для ваших нужд, смотрите документацию «Использование SQLite 3 во Flask».
Шаблоны особенно полезны, если используется наследование. Прочтите документацию как используется наследование в шаблонах. Наследование в шаблонах позволяет сохранить некоторые элементы на каждой страницы (например: заголовок, навигация и футер).
Включено автоматическое экранирование, что позволит избежать проблем, если имя содержит HTML-теги. Если доверяете переменной, а вы знаете, что это будет безопасно в HTML (например, потому что оно пришло от модуля, который преобразует вики-разметки в HTML), вы можете пометить его как безопасный с помощью Markup класса или с помощью |safe фильтра в шаблоне. В документации Jinja 2 представлено несколько примеров.
Вот пример, как работает класс разметки:
Доступ к данным запроса [ править ]
Для веб-приложений крайне важно реагировать на данные клиента отправляя их на сервер. Flask обеспечивает этой информацией — глобальный объект запроса. Если у вас есть некоторый опыт работы с Python, вы можете быть удивлены, как этот объект может быть глобальным, и как Flask удается оставаться потоко-безопасным. Ответ заключается в локальных контекстах:
Локальные контексты (Context Locals) [ править ]
Некоторые объекты во Flask — глобальные, но это не обычный вид глобальных объектов. Эти объекты являются на самом деле прокси к объектам, которые являются локальными для конкретного контекста. Это труднопроизносимо. Но на самом деле довольно легко понять.
Представьте, что контекст обрабатывает поток. Приходит запрос и веб-сервер решает породить новый поток (или что-то другое, основной объект может иметь дело с параллельными системами в отличие от потоков). Когда Flask начинает свою внутреннюю обработку запросов, он выясняет, какой текущий поток является активным контекстом и связывает текущее приложение и WSGI среду в этом контексте (потоке). Он делает это умно, таким образом, чтобы одно приложение может вызвать другое приложение без разрушения.
Итак, что же это значит для вас? В принципе, пока вы тестируете, вы можете полностью это игнорировать. Но вы можете заметить, что код, который зависит от объекта запроса может внезапно сломаться, потому что нет объекта запроса. Решением является создание объекта запроса для себя и привязка его к контексту. Самое простое решение для тестирования, это использование контекст менеджера test_request_context() В сочетании с постановкой, он свяжет тестовый запрос, так что вы можете взаимодействовать с ним. Вот пример:
Другая возможность состоит в передаче всей WSGI среды к методу request_context():
Объект запроса [ править ]
Объект запроса описан в разделе API, и мы не будем рассматривать его здесь подробно (см. запрос). Вот широкий обзор некоторых из наиболее распространенных операций. Прежде всего вы должны импортировать request из Flask:
Чтобы получить доступ к параметрам, указанным в URL (?key=value), Вы можете использовать атрибут args :
Загрузка файла [ править ]
Через Flask легко использовать загрузку файлов. Просто убедитесь, что не забыли поставить атрибут enctype=»multipart/form-data» в вашей HTML форме, иначе браузер не передаст файлы.
Загруженные файлы сохраняются в память сервера или во временное хранилище в файловой системе. Вы можете получить доступ к этим файлам через атрибут files в объекте запроса. Каждый загруженный файл хранится в этом словаре. Он ведет себя так же, как стандартный объект file в Python, но имеет метод save(), который позволяет сохранить этот файл в файловую систему сервера. Вот простой пример, показывающий, как это работает:
Cookies [ править ]
Доступ к куки осуществляется через их атрибут. Для установки кукис, используйте метод set_cookie в объектах запроса. Данный атрибут представляет собой словарь со всеми переданными клиентскими кукис. Если вы хотите использовать сессии, то не используете куки напрямую, вместо них лучше использовать сессии Flask, что добавит вам некоторую безопасность поверх кукис.
Обратите внимание, что куки устанавливаются в объектах ответа. Которые обычно возвращаются как строки и Flask конвертируют в их объекты. Если вы хотите влиять на этот процесс, то используйте функцию make_response()
Редиректы и ошибки [ править ]
Это довольно бессмысленный пример, потому что пользователи будут перенаправлены со страницы индекса. Они не смогут получить доступ (получат ошибку 401 — отказано в доступе), но это показывает, как это работает.
По умолчанию черно-белые страницы ошибок показываются в каждом коде ошибок. Если вы хотите настроить страницу ошибки, вы можете использовать декоратор errorhandler()
Об ответах [ править ]
Возвращаемые значения от обозревающей функции автоматически преобразуется в объект-ответ. То есть если возвращаемое значение является строкой, оно конвертируется в объект-ответ со строкой в ответе тела, код ошибки «200 OK» и text/html mimetype. Логика преобразования для возвращаемого значения выглядит следующим образом:
Если вы хотите заполучить результаты объект-ответ внутри обзора, используйте функцию make_response()
Вам просто нужно обернуть возвращение выражения от make_response() и получить результат объекта, чтобы изменить его, а затем вернуть его обратно:
Сеансы [ править ]
В дополнение к объекту-запроса есть и второй объект под названием сессия, которая сохраняет информацию относящуюся к пользователю от одного запроса к другому. Это осуществляется поверх кукис и записывает куки криптографически. Это означает, что пользователь может посмотреть содержимое кукис, но не изменить его, так как они не знают закрытый ключ, который используется для подписи.
Для того, чтобы использовать сессии вы должны установить секретный ключ. Вот как работают сессии:
escape() — указывается в этом примере, так как в данном случае не используется шаблонизатор.
Как сгенерировать хороший секретный ключ?
Самый простой и наиболее доступный способ, сделать это на основе генератора псевдослучайных чисел.
Небольшое замечание о кукисах основанных на базе сессий: Flask примет значение, положит в объект-сессию и сериализует их в кукисы. Если вы обнаружили, что некоторые значения не сохранились между запросами, то учтите, что кукисы на самом деле активны, и вы не получите четкое сообщение об ошибке, поэтому проверяйте размер куки в ваших ответах на странице по сравнению с размером, который поддерживается веб-браузерами.
Фидбэк, система флэшинга [ править ]
Хорошие приложения и пользовательские интерфейсы, имеют систему обратной связи. Если пользователь не получает достаточно обратной связи, то в конечном итоге, он начнет ненавидеть ваше приложение. Flask дает простой путь, чтобы получить обратную связь с пользователем через флэшинг систему. Флэшинг система в основном записывает сообщения в конце запроса и доступна к нему на следующий (и только на следующий) запрос. Сообщение предоставляется обычно через разметку шаблона.
Для флэш-сообщения используйте метод flash() А чтобы получить сообщение, можете использовать get_flashed_messages(), которые также доступны в шаблонах.
Примеры использования можете посмотреть здесь
Логирование [ править ]
Вы можете оказаться в ситуации, когда вы имеете дело с данными, которые по идее должны быть правильными, но на самом деле это не так. Например, некоторый клиентский код, который посылает HTTP-запрос к серверу. Это может быть вызвано манипуляциями с данными со стороны пользователя, или падение клиентского кода. Вполне нормально ответить на это ошибкой 400 Bad Request, но бывают ситуации, когда несмотря на ошибку, код должен продолжать работать.
Если вы хотите видеть, что произошло что-то подозрительное, используйте логирование.
Подключение WSGI Middlewares [ править ]
Если вы хотите добавить WSGI middleware в ваше приложение, вы можете обернуть его внутри WSGI приложения. Например, если вы хотите добавить middleware от Werkzeug в работе, чтобы обойти ошибки в lighttpd, вы можете сделать это следующим образом:
Учебное пособие [ править ]
Мы назовем наш первый блог Flaskr, не стесняйтесь в выборе имени. В основном мы хотим сделать следующие вещи:
Мы будем использовать напрямую SQLite3, потому что этого достаточно для приложения такого размера. Для приложений большого размера лучше использовать SQLAlchemy, которая обрабатывает подключения к базе данных более разумным способом и дает много возможностей в обработке запросов. Кроме того, есть еще одна из самых популярных баз данных — NoSQL, можно использовать ее, если она вам больше подходит.
Шаг 0: Создание каталогов [ править ]
Вначале создадим каталоги, необходимые Вашему приложению:
Каталог flaskr не пакет Python, а лишь место размещения наших файлов. Непосредственно в эту папку поместим схему нашей базы данных и основной модуль. Файлы каталога static доступны для пользователей через HTTP, оттуда подгружаются css и javascript файлы. В каталоге templates Flask будет искать Jinja2-шаблоны, которые будут созданы в конце урока.
Шаг 1: Схема базы данных [ править ]
Создадим базу данных. Это не сложно, для этого приложения хватит одной таблицы и поддержки только SQLite. Просто поместим файл следующего содержания:
Шаг 2: Установочный код приложения [ править ]
Теперь можно создать практическое приложение и инициализировать его с конфигурацией из того же файла flaskr.py :
from_object() проанализирует данный объект (если это строка, то импортирует её) и найдёт все переменные (в верхнем регистре), определённые там. В нашем случае, конфигурация была в нескольких строках кода, приведенных выше. Её можно поместить в отдельный файл.
Для изменения значений по умолчанию таким способом можно установить в переменной окружения FLASKR_SETTINGS название конфигурационного файла для загрузки. Флаг silent («тихо, безмолвно») отключает вывод сообщений Flask при отсутствии такой переменной окружения.
Секретный ключ ( SECRET_KEY ) необходим для безопасности клиентских сессий. Вдумчиво выбирайте ключевые слова: они должны быть настолько сложными, насколько это возможно.
Флаг отладки ( DEBUG ) включает или выключает интерактивный отладчик. Никогда не оставляйте режим отладки активным на производственном сервере, это позволит пользователям выполнять код на нём!
Добавим метод для подключения к указанной базе данных. Он может быть использован для соединения по запросу, а также из интерактивной оболочки Python или скрипта. Этот метод пригодится позже.
Наконец, если нужно запустить этот файл в качестве отдельного приложения, просто добавим в конец строку, запускающую сервер:
Шаг 3: Создание базы данных [ править ]
Flaskr — приложение на основе базы данных, а, точнее, реляционной базы данных. Такие системы нуждаются в схеме, сообщающей, как хранить информацию. Поэтому, важно создать такую схему перед первым запуском сервера.
Такая схема может быть создана передачей файла schema.sql в sqlite3 :
Соединяясь с базой данных, получаем объект связи (называемый db ), предоставляющий нам курсор cursor с методом для выполнения всего сценария. В конце нужно подтвердить ( commit ) изменения. SQLite3 и другие транзакционные базы данных не подтверждают операций без Вашего особого распоряжения.
Теперь у нас появилась возможность создать базу данных в оболочке Python, импортировав и вызвав созданную функцию:
Поиск и устранение неисправностей [ править ]
Получив сообщение об ошибке, что таблица не может быть найдена, убедитесь, что сделан вызов функции init_db() и правильно указаны названия таблиц (наиболее частая ошибка — путаница с множественным и единственным числом в названиях таблиц).
Шаг 4: Запрос подключения к базе данных [ править ]
Теперь мы знаем, как открыть соединения с базой данных и использовать их в скриптах, но как сделать эти запросы элегантно? Нам понадобится подключение к базе данных во всех наших функциях, так что имеет смысл инициализировать соединения перед каждым запросом и закрыть их после него.
Совет [ править ]
Шаг 5: Функции представления [ править ]
Теперь, когда у нас уже есть соединения с базой данных, мы можем приступить к написанию функций представления. Нам понадобится четыре:
Вывод записей [ править ]
Этот вывод показывает все записи сохраненные в базе данных. Он мониторит корневой каталог приложения и выбирает по заголовку и тексту из базы данных. Запись с наибольшим идентификатором (новейшая запись) будет сверху. Ряды возвращаемые от курсора являются кортежем с колонками, и выбираются специфично по запросу. Это хорошо для небольших приложений, как здесь, но вы можете конвертировать их в словарь. Если вы заинтересованы, чтобы сделать это, то посмотрите как это сделано в Easy Querying.
Эта обзорная функция пропускает записи через словари в шаблоне show_entries.html и возвращает обработанное значение:
Добавление новых записей [ править ]
Эта страницы позволяет залогиненному пользователю добавлять новые записи. Это просто ответ на POST-запрос. Форма для данных показывается на странице отображения записей (show_entries). Если все сработало как надо, мы показываем (flash()) сообщение и производим перенаправление на страницу отображения записей:
Обратите внимание, что мы проверяем, залогинен ли пользователь, по ключу (ключ logged_in существует в пределах сессии и равен True).
Замечание о безопасности: убедитесь, что вы используете знаки вопроса (?) при составлении SQL-запроса, аналогично примеру выше. Если при составлении запроса вы используете форматированные строки, ваше приложение может быть уязвимо к атакам типа sql-injection. См. Using SQLite 3 with Flask
Функции login и logout [ править ]
Эти функции используются для входа и выхода пользователей сайта. Login проверяет имя пользователя и его пароль и устанавливает для сессии параметр logged_in. Если вход пользователя произошел успешно, то значение этого параметра устанавливается равным True, и пользователь перенаправляется обратно на страницу show_entries. Кроме того, пользователю выдается сообщение о том, что он успешно зашел на сайт. Если же происходит ошибка, то шаблон страницы логина выдает сообщение об этом, и запрос к пользователю повторяется.
В свою очередь, функция logout удаляет параметр logged_in из сессии. Здесь мы использовали следующий трюк: если мы будем использовать метод словаря (dict) pop(), и передадим в него второй параметр (значение по умолчанию), то метод удалит ключ из словаря, если он там есть, и не сделает ничего, если его нет. Трюк полезен, потому что нам не нужно проверять, был залогинен ли пользователь.
Шаг 6: Шаблоны [ править ]
Теперь мы можем начать работу с шаблонами. Если мы будем переходить по URL примера прямо сейчас, мы получим исключение, из-за того что Фласк не может найти шаблоны. Шаблоны используют синтаксис Jinja2, по умолчанию включено автоматическое экранирование символов. Это значит, что если вы не разметите значения в коде метками Markup или фильтром |safe в шаблоне, то Jinja2 будет обеспечивать экранирование спецсимволов вроде их XML-эквивалентами.
Мы так же будем пользоваться наследованием шаблонов, что делает возможным повторное использование одного макета сайта на всех его страницах.
Поместите следующие шаблоны в папку templates:
layout.html [ править ]
Этот шаблон содержит основную структуру html, шапку и ссылку на вход на сайт (или на выход, если пользователь уже залогинен). Так же он показывает всплывающие сообщения, если таковые появятся. Блок может быть заменен блоком с таким же именем (body) в шаблоне-наследнике.
Словарь session доступен на уровне шаблонов, и вы можете использовать его для проверки, залогинен ли пользователь. Обратите внимание, что в Jinja вы можете получать отсутствующие атрибуты и элементы объектов/словарей, так что следующий код будет работать, даже если в сессии отсутствует параметр logged_in:
show_entries.html [ править ]
Этот шаблон расширяет предыдущий шаблон layout.html и показывает сообщения нашего блога. Обратите внимание, что цикл for перебирает сообщения, которые мы передали через функцию render_template(). Так же мы выводим форму для функции add_entry и используем POST-запрос.
login.html [ править ]
И наконец, шаблон для входа на сайт, который просто показывает пользователю форму логина:
Шаг 7. Добавляем стиль [ править ]
Теперь, когда все работает, самое время сделать наше приложение стильным. Просто создайте страницу стилей с названием style.css в папке static, которую мы создали раньше:
Бонус: тестируем приложение [ править ]
Теперь, когда вы закончили работу над этим приложением, и все работает как надо, будет хорошей идеей добавить автоматизированные тесты, чтобы упростить будущие модификации. Это приложение используется как пример для выполнения юнит-тестирования в разделе документации Testing Flask Applications. Сходите, посмотрите, как просто тестировать приложения на Flask-e