Расширения Flask
Расширения Flask — это пакеты, которые можно установить, чтобы расширить возможности Flask. Их суть в том, чтобы обеспечить удобный и понятный способ интеграции пакетов во Flask. Посмотреть все доступные расширения можно на странице https://flask.pocoo.org/extenstions/. На странице есть пакеты, возможности которых варьируются от отправки email до создания полноценных интерфейсов администратора. Важно помнить, что расширять возможности Flask можно не только с помощью его расширений. На самом деле, подойдет любой пакет из стандартной библиотеки Python или PyPi. Оставшаяся часть урока посвящена тому, как установить и интегрировать удобное расширение для Flask под названием Flask-Script.
Расширение Flask-Script
Flask-Script — это удобное миниатюрное расширение, которое позволяет создавать интерфейсы командной строки, запускать сервер и консоль Python в контексте приложений, делать определенные переменные видимыми в консоли автоматически и так далее.
Стоит напомнить то, что обсуждалось в уроке «Основы Flask». Для запуска сервера разработки на конкретном хосте и порте, их нужно передать в качестве аргументов-ключевых слов методу run()
:
if __name__ == "__main__":
app.run(debug=True, host="127.0.0.10", port=9000)
Проблема в том, что такой подход не гибкий. Намного удобнее передать хост и порт в виде параметров командной строки при запуске сервера. Flask-Script позволяет сделать это. Установить Flask-Script можно с помощью pip:
(env) gvido@vm:~/flask_app$ pip install flask-script
Чтобы использовать Flask-Script сперва нужно импортировать класс Manager
из пакета flask_script
и создать экземпляр объекта Manager
, передав ему экземпляр приложения. Таким образом расширения Flask интегрируются. Сначала импортируется нужный класс из пакета, а затем создается экземпляр с помощью передачи ему экземпляра приложения. Нужно открыть файл main2.py
и изменить его следующим образом:
from flask import Flask, render_template
from flask_script import Manager
app = Flask(__name__)
manager = Manager(app)
#...
Созданный объект Manager
также имеет метод run()
, который помимо запуска сервера разработки может считывать аргументы командной строки. Следует заменить строку app.run(debug=True)
на manager.run()
. К этому моменту main2.py
должен выглядеть вот так:
from flask import Flask, render_template
from flask_script import Manager
app = Flask(__name__)
manager = Manager(app)
@app.route('/')
def index():
return render_template('index.html', name='Jerry')
@app.route('/user/<int:user_id>/')
def user_profile(user_id):
return "Profile page of user #{}".format(user_id)
@app.route('/books/<genre>/')
def books(genre):
return "All Books in {} category".format(genre)
if __name__ == "__main__":
manager.run()
Теперь у приложения есть доступ к базовым командам. Чтобы посмотреть, какие из них доступны, необходимо запустить файл main2.py
:
(env) gvido@vm:~/flask_app$ python main2.py
usage: main2.py [-?] {shell,runserver} ...
positional arguments:
{shell,runserver}
shell Runs a Python shell inside Flask application context.
runserver Runs the Flask development server i.e. app.run()
optional arguments:
-?, --help show this help message and exit
Как показывает вывод, сейчас есть всего две команды: shell
и runserver
. Начнем с команды runserver
.
runserver
запускает веб-сервер. По умолчанию, он запускается на 127.0.0.1 на порте 5000. Чтобы увидеть варианты для любой команды нужно ввести --help
и саму команду. Например:
(env) gvido@vm:~/flask_app$ python main2.py runserver --help
usage: main2.py runserver [-?] [-h HOST] [-p PORT] [--threaded]
[--processes PROCESSES] [--passthrough-errors] [-d]
[-D] [-r] [-R] [--ssl-crt SSL_CRT]
[--ssl-key SSL_KEY]
Runs the Flask development server i.e. app.run()
optional arguments:
-?, --help show this help message and exit
-h HOST, --host HOST
-p PORT, --port PORT
--threaded
--processes PROCESSES
--passthrough-errors
-d, --debug enable the Werkzeug debugger (DO NOT use in production
code)
-D, --no-debug disable the Werkzeug debugger
-r, --reload monitor Python files for changes (not 100% safe for
production use)
-R, --no-reload do not monitor Python files for changes
--ssl-crt SSL_CRT Path to ssl certificate
--ssl-key SSL_KEY Path to ssl key
Самые широко используемые варианты для runserver
— это --host
и --post
. С их помощью можно запустить сервер разработки на конкретном интерфейсе и порте. Например:
(env) gvido@vm:~/flask_app$ python main2.py runserver --host=127.0.0.2 --port 8000
* Running on http://127.0.0.2:8000/ (Press CTRL+C to quit)
По умолчанию команда runserver
запускает сервер без отладчика. Включить его вручную можно следующим образом:
(env) gvido@vm:~/flask_app$ python main2.py runserver -d -r
* Restarting with stat
* Debugger is active!
* Debugger PIN: 250-045-653
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Более простой способ запустить отладчик — выбрать значение True
для атрибута debug
у экземпляра объекта (app
). Для этого нужно открыть main2.py
и изменить файл следующим образом:
#...
app = Flask(__name__)
app.debug = True
manager = Manager(app)
#...
Далее о команде shell
.
shell
запускает консоль Python в контексте приложения Flask. Это значит, что все объекты внутри контекстов приложения и запроса будут доступны в консоли без создания дополнительных контекстов. Для запуска консоли нужно ввести следующую команду.
(env) gvido@vm:~/flask_app$ python main2.py shell
Получим доступ к определенным объектам.
>>>
>>> from flask import current_app, url_for, request
>>>
>>> current_app.name
'main2'
>>>
>>>
>>> url_for("user_profile", user_id=10)
'/user/10/'
>>>
>>> request.path
'/'
>>>
Как и ожидалось, это можно сделать, не создавая контексты приложения и запроса.
Создание команд
Когда экземпляр Manager
создан, можно приступать к созданию собственных команд. Есть два способа:
- С помощью класса
Command
- С помощью декоратора
@command
Создание команд с помощью класса Command
В файле main2.py
добавим класс Faker
:
#...
from flask_script import Manager, Command
#...
manager = Manager(app)
class Faker(Command):
'Команда для добавления поддельных данных в таблицы'
def run(self):
# логика функции
print("Fake data entered")
@app.route('/')
#...
Команда Faker
была создана с помощью наследования класса Command
. Метод run()
вызывается при исполнении команды. Чтобы выполнить команду через командную строку, ее нужно добавить в экземпляр Manager
с помощью метода add_command()
:
#...
class Faker(Command):
'Команда для добавления поддельных данных в таблицы'
def run(self):
# логика функции
print("Fake data entered")
manager.add_command("faker", Faker())
#...
Теперь нужно снова вернуться в терминал и запустить файл main2.py
:
(env) gvido@vm:~/flask_app$ python main2.py
usage: main2.py [-?] {faker,shell,runserver} ...
positional arguments:
{faker,shell,runserver}
faker Команда для добавления поддельных данных в таблицы
shell Runs a Python shell inside Flask application context.
runserver Runs the Flask development server i.e. app.run()
optional arguments:
-?, --help show this help message and exit
Стоит обратить внимание, что теперь, в дополнение к shell
и runserver
, есть команда faker
. Описание перед самой командой взято из строки документации класса Faker
. Для запуска нужно ввести следующую команду:
(env) gvido@vm:~/flask_app$ python main2.py faker
Fake data entered
Создание команд с помощью декоратора @command
Создание команд с помощью класса Command
достаточно объемно. Как вариант, можно использовать декоратор @command
экземпляра класса Manager
. Для этого нужно открыть файл main2.py
и изменить его следующим образом:
#...
manager.add_command("faker", Faker())
@manager.command
def foo():
"Это созданная команда"
print("foo command executed")
@app.route('/')
#...
Была создана простая команда foo
, которая выводит foo command executed
при вызове. Декоратор @command
автоматически добавляет команду к существующему экземпляру Manager
, так что не нужно вызывать метод add_command()
. Чтобы увидеть, как используются команды, нужно вернуться обратно в терминал и запустить main2.py
.
(env) gvido@vm:~/flask_app$ python main2.py
usage: main2.py [-?] {faker,foo,shell,runserver} ...
positional arguments:
{faker,foo,shell,runserver}
faker Команда для добавления поддельных данных в таблицы
foo Это созданная команда
shell Runs a Python shell inside Flask application context.
runserver Runs the Flask development server i.e. app.run()
optional arguments:
-?, --help show this help message and exit
Поскольку команда foo
теперь доступна, ее можно исполнить, введя следующую команду.
(env) gvido@vm:~/flask_app$ python main2.py foo
foo command executed
Автоматический импорт объектов
Импорт большого количества объектов в командной строке может быть утомительным. С помощью Flask-Script объекты можно сделать видимыми в терминале без явного импорта.
Команда Shell
запускает оболочку. Функция конструктора оболочки Shell
принимает аргумент-ключевое слово make_context
. Аргумент, передаваемый make_context
должен быть вызываемым и возвращать словарь. По умолчанию вызываемый объект возвращает словарь, содержащий только экземпляр приложения, то есть app
. Это значит, что по умолчанию в оболочке можно получить доступ только к экземпляру приложения (app
), специально не импортируя его. Чтобы изменить это поведение, нужно назначить новому объекту (функции), поддерживающему вызов, make_context
. Это вернет словарь с объектами, к которым требуется получить доступ внутри оболочки.
Откроем файл main2.py
, чтобы добавить следующий код после функции foo()
.
#...
from flask_script import Manager, Command, Shell
#...
def shell_context():
import os, sys
return dict(app=app, os=os, sys=sys)
manager.add_command("shell", Shell(make_context=shell_context))
#...
Здесь вызываемой функции shell_context()
передается аргумент-ключевое слово make_context
. Функция shell_context
возвращает словарь с тремя объектами: app, os
и sys
. В результате, внутри оболочки теперь есть доступ к этим объектам, хотя их импорт не производился.
(env) gvido@vm:~/flask_app$ python main2.py shell
>>>
>>> app
<Flask 'main2'>
>>>
>>> os.name
'posix'
>>>
>>> sys.platform
'linux'
>>>
>>>