Быстрый старт
Вы хотите начать работу? Эта страница даёт хорошее введение в Flask. Сначала выполните Установку, чтобы настроить проект и установить Flask.
Минимальное приложение
Минимальное приложение Flask выглядит примерно так:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello_world():
return "<p>Hello, World!</p>"
Что делает этот код?
- Сначала мы импортировали класс
Flask. Экземпляр этого класса будет нашим приложением WSGI. - Далее мы создаём экземпляр этого класса. Первым аргументом является имя модуля или пакета приложения.
__name__— удобное сокращение, подходящее для большинства случаев. Это необходимо, чтобы Flask знал, где искать ресурсы, такие как шаблоны и статические файлы. - Затем мы используем декоратор
route(), чтобы указать Flask, какой URL должен вызывать нашу функцию. - Функция возвращает сообщение, которое мы хотим отобразить в браузере пользователя. По умолчанию тип контента — HTML, поэтому HTML в строке будет рендериться браузером.
Сохраните его как hello.py или что-то подобное. Убедитесь, что вы не назвали своё приложение flask.py, так как это вызовет конфликт с самим Flask.
Чтобы запустить приложение, используйте команду flask или python -m flask. Вы должны указать Flask, где находится ваше приложение, используя опцию --app.
$ flask --app hello run * Serving Flask app 'hello' * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
Поведение обнаружения приложения
В качестве сокращения, если файл называется app.py или wsgi.py, вам не нужно использовать --app. См. Интерфейс командной строки для получения дополнительной информации.
Это запускает очень простой встроенный сервер, который достаточно хорош для тестирования, но, вероятно, не то, что вы хотите использовать в рабочей среде. Для вариантов развертывания см. Развертывание в рабочей среде.
Теперь перейдите по адресу http://127.0.0.1:5000/, и вы должны увидеть приветствие "hello world".
Если другая программа уже использует порт 5000, вы увидите OSError: [Errno 98] или OSError: [WinError 10013] при попытке запуска сервера. См. Порт уже занят, чтобы разобраться с этим.
Внешне видимый сервер
Если вы запустите сервер, вы заметите, что к нему можно получить доступ только с вашего компьютера, а не с любого другого в сети. Это значение по умолчанию, потому что в режиме отладки пользователь приложения может выполнить произвольный код Python на вашем компьютере.
Если отладчик отключён или вы доверяете пользователям в вашей сети, вы можете сделать сервер общедоступным, просто добавив --host=0.0.0.0 в командную строку:
$ flask run --host=0.0.0.0
Это сообщает вашей операционной системе прослушивать все публичные IP-адреса.
Режим отладки
Команда flask run может делать больше, чем просто запускать сервер разработки. Включив режим отладки, сервер будет автоматически перезагружаться при изменении кода и покажет интерактивный отладчик в браузере, если во время запроса произойдёт ошибка.
Предупреждение
Отладчик позволяет выполнять произвольный код Python из браузера. Он защищён пином, но всё равно представляет собой серьёзную угрозу безопасности. Не запускайте сервер разработки или отладчик в рабочей среде.
Чтобы включить режим отладки, используйте опцию --debug.
$ flask --app hello run --debug * Serving Flask app 'hello' * Debug mode: on * Running on http://127.0.0.1:5000 (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: nnn-nnn-nnn
См. также:
- Сервер разработки и Интерфейс командной строки для получения информации о работе в режиме отладки.
- Отладка ошибок приложения для получения информации об использовании встроенного отладчика и других отладчиков.
- Ведение журнала и Обработка ошибок приложения для ведения журнала ошибок и отображения приятных страниц с ошибками.
Экранирование HTML
При возвращении HTML (тип ответа по умолчанию в Flask), любые пользовательские значения, рендеренные в выводе, должны быть экранированы, чтобы защититься от атак с внедрением кода. HTML-шаблоны, рендеренные с помощью Jinja, представленные позже, сделают это автоматически.
escape(), показанный здесь, может использоваться вручную. Он опущен в большинстве примеров для краткости, но вы всегда должны знать, как используете недоверенные данные.
from markupsafe import escape
@app.route("/<name>")
def hello(name):
return f"Hello, {escape(name)}!"
Если пользователь смог отправить имя <script>alert("bad")</script>, экранирование приведет к тому, что оно будет отображено как текст, а не выполнит скрипт в браузере пользователя.
<name> в маршруте захватывает значение из URL и передает его функции представления. Правила переменных объяснены ниже.
Маршрутизация
Современные веб-приложения используют осмысленные URL-адреса, чтобы помочь пользователям. Пользователи с большей вероятностью оценят страницу и вернутся на неё, если она использует осмысленный URL-адрес, который они могут запомнить и использовать для прямого перехода на страницу.
Используйте декоратор route(), чтобы привязать функцию к URL-адресу.
@app.route('/')
def index():
return 'Index Page'
@app.route('/hello')
def hello():
return 'Hello, World'
Вы можете сделать больше! Вы можете сделать части URL динамическими и прикрепить к функции несколько правил.
Правила переменных
Вы можете добавить переменные части в URL-адрес, обозначив их <variable_name>. Ваша функция затем получает <variable_name> в качестве аргумента ключевого слова. Дополнительно вы можете использовать преобразователь для указания типа аргумента, как в <converter:variable_name>.
from markupsafe import escape
@app.route('/user/<username>')
def show_user_profile(username):
# show the user profile for that user
return f'User {escape(username)}'
@app.route('/post/<int:post_id>')
def show_post(post_id):
# show the post with the given id, the id is an integer
return f'Post {post_id}'
@app.route('/path/<path:subpath>')
def show_subpath(subpath):
# show the subpath after /path/
return f'Subpath {escape(subpath)}'
Типы преобразователей:
| (по умолчанию) принимает любой текст без косой черты |
| принимает положительные целые числа |
| принимает положительные значения с плавающей точкой |
| как |
| принимает строки UUID |
Уникальные URL-адреса/Поведение перенаправления
Следующие два правила отличаются использованием косой черты в конце.
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/about')
def about():
return 'The about page'
Канонический URL-адрес для projects конечной точки имеет косую черту в конце. Он похож на папку в файловой системе. Если вы обращаетесь по URL-адресу без косой черты в конце (/projects), Flask перенаправляет вас на канонический URL-адрес с косой чертой в конце (/projects/).
Канонический URL-адрес для about конечной точки не имеет косой черты в конце. Он похож на имя файла. Обращение по URL-адресу с косой чертой в конце (/about/ ) приводит к ошибке 404 «Не найдено». Это помогает поддерживать уникальность URL-адресов для этих ресурсов, что помогает поисковым системам избежать индексации одной и той же страницы дважды.
Создание URL-адресов
Чтобы создать URL-адрес для конкретной функции, используйте функцию url_for(). Она принимает имя функции в качестве первого аргумента и любое количество аргументов ключевых слов, каждый из которых соответствует переменной части правила URL-адреса. Неизвестные части переменной добавляются в URL-адрес в качестве параметров запроса.
Почему вы хотите создавать URL-адреса с помощью функции обратного преобразования URL-адресов url_for(), а не встраивать их напрямую в шаблоны?
- Обратное преобразование часто более описательно, чем непосредственное встраивание URL-адресов.
- Вы можете изменить URL-адреса в одном месте, вместо того, чтобы запоминать и вручную изменять жёстко закодированные URL-адреса.
- Создание URL-адресов обрабатывает экранирование специальных символов прозрачно.
- Сгенерированные пути всегда абсолютны, избегая неожиданного поведения относительных путей в браузерах.
- Если ваше приложение размещено вне корня URL-адреса, например, в
/myapplicationвместо/,url_for()правильно обрабатывает это за вас.
Например, здесь мы используем метод test_request_context(), чтобы попробовать url_for(). test_request_context() сообщает Flask, что он обрабатывает запрос, даже когда мы используем оболочку Python. См. Локальные переменные контекста.
from flask import url_for
@app.route('/')
def index():
return 'index'
@app.route('/login')
def login():
return 'login'
@app.route('/user/<username>')
def profile(username):
return f'{username}\'s profile'
with app.test_request_context():
print(url_for('index'))
print(url_for('login'))
print(url_for('login', next='/'))
print(url_for('profile', username='John Doe'))
/ /login /login?next=/ /user/John%20Doe
Методы HTTP
Веб-приложения используют различные методы HTTP при обращении к URL-адресам. Вы должны ознакомиться с методами HTTP, работая с Flask. По умолчанию маршрут отвечает только на запросы GET. Вы можете использовать аргумент methods декоратора route(), чтобы обработать различные методы HTTP.
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return do_the_login()
else:
return show_the_login_form()
В приведённом выше примере все методы для маршрута находятся в одной функции, что может быть полезно, если каждая часть использует какие-то общие данные.
Вы также можете разделить представления для разных методов на разные функции. Flask предоставляет сокращения для декорации таких маршрутов с помощью get(), post() и т. д. для каждого распространённого метода HTTP.
@app.get('/login')
def login_get():
return show_the_login_form()
@app.post('/login')
def login_post():
return do_the_login()
Если GET присутствует, Flask автоматически добавляет поддержку метода HEAD и обрабатывает запросы HEAD в соответствии с RFC HTTP. Аналогично, OPTIONS автоматически реализуется для вас.
Статические файлы
Динамические веб-приложения также нуждаются в статических файлах. Обычно там находятся CSS и JavaScript файлы. В идеале ваш веб-сервер настроен для их предоставления, но во время разработки Flask может это сделать тоже. Просто создайте папку под названием static в своём пакете или рядом с модулем, и она будет доступна по адресу /static в приложении.
Для генерации URL для статических файлов используйте специальное имя конечной точки 'static':
url_for('static', filename='style.css')
Файл должен храниться в файловой системе как static/style.css.
Рендеринг шаблонов
Генерация HTML внутри Python не является приятной задачей, а на самом деле довольно громоздкой, потому что вам нужно самостоятельно выполнять экранирование HTML, чтобы защитить приложение. По этой причине Flask автоматически настраивает движок шаблонов Jinja2 для вас.
Шаблоны могут использоваться для генерации любого типа текстовых файлов. Для веб-приложений вы в первую очередь будете генерировать HTML-страницы, но также можете генерировать Markdown, простой текст для писем и многое другое.
Для справки по HTML, CSS и другим веб-API используйте MDN Web Docs.
Для рендеринга шаблона можно использовать метод render_template(). Все, что вам нужно сделать, это указать имя шаблона и переменные, которые вы хотите передать в движок шаблонов в качестве ключевых аргументов. Вот простой пример того, как рендерить шаблон:
from flask import render_template
@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
return render_template('hello.html', name=name)
Flask будет искать шаблоны в папке templates. Таким образом, если ваше приложение является модулем, эта папка расположена рядом с этим модулем, если это пакет, то она находится внутри пакета:
Случай 1: модуль:
/application.py
/templates
/hello.html
Случай 2: пакет:
/application
/__init__.py
/templates
/hello.html
Для шаблонов можно использовать всю мощь шаблонов Jinja2. Для получения дополнительной информации перейдите к официальной документации по шаблонам Jinja2.
Вот пример шаблона:
<!doctype html>
<title>Hello from Flask</title>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello, World!</h1>
{% endif %}
Внутри шаблонов у вас также есть доступ к объектам config, request, session и g [1], а также к функциям url_for() и get_flashed_messages().
Шаблоны особенно полезны при использовании наследования. Если вы хотите узнать, как это работает, см. Наследование шаблонов. В основном наследование шаблонов позволяет сохранять определённые элементы на каждой странице (например, заголовок, навигацию и подвал).
Автоматическое экранирование включено, поэтому, если name содержит HTML, оно будет автоматически экранировано. Если вы можете доверять переменной и знаете, что она будет безопасным HTML (например, потому что она получена из модуля, который преобразует разметку вики в HTML), вы можете пометить её как безопасную, используя класс Markup или используя фильтр |safe в шаблоне. Для получения дополнительных примеров обратитесь к документации Jinja 2.
Вот базовое введение в работу класса Markup:
>>> from markupsafe import Markup
>>> Markup('<strong>Hello %s!</strong>') % '<blink>hacker</blink>'
Markup('<strong>Hello <blink>hacker</blink>!</strong>')
>>> Markup.escape('<blink>hacker</blink>')
Markup('<blink>hacker</blink>')
>>> Markup('<em>Marked up</em> » HTML').striptags()
'Marked up » HTML'
Журнал изменений
Изменено в версии 0.5: Автоэкранирование больше не включено для всех шаблонов. Следующие расширения для шаблонов активируют автоэкранирование: .html, .htm, .xml, .xhtml. Шаблоны, загруженные из строки, будут иметь отключенное автоэкранирование.
Получение данных запроса
Для веб-приложений крайне важно реагировать на данные, которые клиент отправляет на сервер. В Flask эта информация предоставляется глобальным объектом request. Если у вас есть опыт работы с Python, вы, вероятно, задаетесь вопросом, как этот объект может быть глобальным и как Flask все же остается потокобезопасным. Ответ — контекстные локальные переменные:
Контекстные локальные переменные
Внутренняя информация
Если вы хотите понять, как это работает и как можно реализовать тесты с контекстными локальными переменными, прочитайте этот раздел, в противном случае просто пропустите его.
Некоторые объекты в Flask являются глобальными, но не в обычном смысле. Эти объекты на самом деле являются прокси к объектам, которые являются локальными для определенного контекста. Как многословно. Но это на самом деле довольно легко понять.
Представьте, что контекст — это обрабатывающая нить. Запрос поступает, и веб-сервер решает запустить новую нить (или что-то другое, базовый объект способен обрабатывать системы конкуретности, отличные от нитей). Когда Flask запускает свою внутреннюю обработку запроса, он определяет, что текущая нить — активный контекст, и привязывает текущее приложение и окружение WSGI к этому контексту (нити). Он делает это интеллектуальным способом, чтобы одно приложение могло вызывать другое приложение без сбоев.
Что это означает для вас? В основном вы можете полностью игнорировать это, если не занимаетесь чем-то вроде тестирования. Вы заметите, что код, зависящий от объекта запроса, внезапно сломается, потому что объекта запроса нет. Решение — создать объект запроса самостоятельно и привязать его к контексту. Самое простое решение для тестирования — использовать контекстный менеджер test_request_context(). В сочетании с инструкцией with он привяжет тестовый запрос, чтобы вы могли взаимодействовать с ним. Вот пример:
from flask import request
with app.test_request_context('/hello', method='POST'):
# now you can do something with the request until the
# end of the with block, such as basic assertions:
assert request.path == '/hello'
assert request.method == 'POST'
Другой вариант — передать все окружение WSGI методу request_context():
with app.request_context(environ):
assert request.method == 'POST'
Объект запроса
Объект запроса документирован в разделе API, и мы не будем подробно рассматривать его здесь (см. Request). Вот краткий обзор некоторых наиболее распространенных операций. Во-первых, вы должны импортировать его из модуля flask:
from flask import request
Текущий метод запроса доступен с помощью атрибута method. Для доступа к данным формы (данные, передаваемые в запросе POST или PUT) можно использовать атрибут form. Вот полный пример двух упомянутых выше атрибутов:
@app.route('/login', methods=['POST', 'GET'])
def login():
error = None
if request.method == 'POST':
if valid_login(request.form['username'],
request.form['password']):
return log_the_user_in(request.form['username'])
else:
error = 'Invalid username/password'
# the code below is executed if the request method
# was GET or the credentials were invalid
return render_template('login.html', error=error)
Что произойдет, если ключ не существует в атрибуте form? В этом случае генерируется специальное исключение KeyError. Вы можете перехватить его как стандартное исключение KeyError, но если этого не сделать, вместо этого отобразится страница ошибки HTTP 400 Bad Request. Поэтому во многих ситуациях вам не нужно иметь с этим проблем.
Для доступа к параметрам, переданным в URL (?key=value), можно использовать атрибут args:
searchword = request.args.get('key', '')
Мы рекомендуем получать доступ к параметрам URL с помощью get или перехватывая KeyError, потому что пользователи могут изменить URL, и в этом случае отображение страницы с ошибкой 400 bad request неудобно.
Полный список методов и атрибутов объекта запроса см. в документации Request.
Загрузка файлов
Вы можете легко обрабатывать загруженные файлы с помощью Flask. Просто не забудьте установить атрибут enctype="multipart/form-data" в вашей HTML-форме, в противном случае браузер вообще не передаст ваши файлы.
Загруженные файлы хранятся в памяти или в временном месте на файловой системе. Вы можете получить доступ к этим файлам, обратившись к атрибуту files объекта запроса. Каждый загруженный файл хранится в этом словаре. Он ведет себя как стандартный объект Python file, но также имеет метод save(), который позволяет сохранить этот файл на файловой системе сервера. Вот простой пример, демонстрирующий, как это работает:
from flask import request
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/uploaded_file.txt')
...
Если вы хотите узнать, как файл был назван на клиенте до загрузки его в ваше приложение, вы можете получить доступ к атрибуту filename. Однако имейте в виду, что это значение может быть подделано, поэтому никогда не доверяйте этому значению. Если вы хотите использовать имя файла клиента для хранения файла на сервере, передайте его через функцию secure_filename(), предоставляемую Werkzeug:
from werkzeug.utils import secure_filename
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
file = request.files['the_file']
file.save(f"/var/www/uploads/{secure_filename(file.filename)}")
...
Для получения дополнительных примеров см. Загрузка файлов.
Перенаправления и ошибки
Для перенаправления пользователя на другой конечный пункт используйте функцию redirect(); для преждевременного прерывания запроса с кодом ошибки используйте функцию abort():
from flask import abort, redirect, url_for
@app.route('/')
def index():
return redirect(url_for('login'))
@app.route('/login')
def login():
abort(401)
this_is_never_executed()
Это довольно бессмысленный пример, потому что пользователь будет перенаправлен с главной страницы на страницу, к которой он не имеет доступа (401 означает отказ в доступе), но он показывает, как это работает.
По умолчанию для каждого кода ошибки отображается чёрно-белая страница ошибки. Если вы хотите настроить страницу ошибки, вы можете использовать декоратор errorhandler():
from flask import render_template
@app.errorhandler(404)
def page_not_found(error):
return render_template('page_not_found.html'), 404
Обратите внимание на 404 после вызова render_template(). Это говорит Flask, что код состояния этой страницы должен быть 404, что означает «не найдено». По умолчанию предполагается 200, что означает: всё прошло хорошо.
См. Обработка ошибок приложения для получения дополнительной информации.
О ответах
Значение, возвращаемое функцией представления, автоматически преобразуется в объект ответа для вас. Если возвращаемое значение является строкой, оно преобразуется в объект ответа со строкой в качестве тела ответа, кодом состояния 200 OK и MIME-типом text/html. Если возвращаемое значение является словарем или списком, вызывается jsonify(), чтобы создать ответ. Логика, которую Flask применяет для преобразования значений возврата в объекты ответа, такова:
- Если возвращается объект ответа правильного типа, он возвращается напрямую из представления.
- Если это строка, создается объект ответа с этими данными и значениями по умолчанию.
- Если это итератор или генератор, возвращающий строки или байты, он обрабатывается как ответ потокового типа.
- Если это словарь или список, объект ответа создается с использованием
jsonify(). - Если возвращается кортеж, элементы кортежа могут предоставить дополнительную информацию. Такие кортежи должны быть в форме
(response, status),(response, headers), или(response, status, headers). Значениеstatusпереопределит код состояния, аheadersможет быть списком или словарем дополнительных значений заголовков. - Если ни один из этих вариантов не подходит, Flask предположит, что возвращаемое значение является допустимым приложением WSGI, и преобразует его в объект ответа.
Если вы хотите получить доступ к результирующему объекту ответа внутри представления, вы можете использовать функцию make_response().
Представьте, что у вас есть представление такого вида:
from flask import render_template
@app.errorhandler(404)
def not_found(error):
return render_template('error.html'), 404
Вам просто нужно обернуть выражение возврата функцией make_response() и получить объект ответа для его изменения, а затем вернуть его:
from flask import make_response
@app.errorhandler(404)
def not_found(error):
resp = make_response(render_template('error.html'), 404)
resp.headers['X-Something'] = 'A value'
return resp
API с JSON
Распространённым форматом ответа при написании API является JSON. Легко начать писать такой API с помощью Flask. Если вы возвращаете dict или list из представления, это будет преобразовано в ответ JSON.
@app.route("/me")
def me_api():
user = get_current_user()
return {
"username": user.username,
"theme": user.theme,
"image": url_for("user_image", filename=user.image),
}
@app.route("/users")
def users_api():
users = get_all_users()
return [user.to_json() for user in users]
Это сокращённый способ передачи данных функции jsonify(), которая сериализует любой поддерживаемый тип данных JSON. Это означает, что все данные в словаре или списке должны быть сериализуемы в JSON.
Для сложных типов, таких как модели баз данных, вам необходимо использовать библиотеку сериализации, чтобы сначала преобразовать данные в допустимые типы JSON. Существует множество библиотек сериализации и расширений API Flask, поддерживаемых сообществом, которые поддерживают более сложные приложения.
Сессии
В дополнение к объекту запроса также есть второй объект, называемый session, который позволяет хранить информацию, специфичную для пользователя, от одного запроса к другому. Это реализовано поверх куки и криптографически подписывает куки. Это означает, что пользователь может просмотреть содержимое вашего куки, но не может его изменить, если ему не известен секретный ключ, используемый для подписи.
Для использования сессий необходимо установить секретный ключ. Вот как работают сессии:
from flask import session
# Set the secret key to some random bytes. Keep this really secret!
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'
@app.route('/')
def index():
if 'username' in session:
return f'Logged in as {session["username"]}'
return 'You are not logged in'
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
session['username'] = request.form['username']
return redirect(url_for('index'))
return '''
<form method="post">
<p><input type=text name=username>
<p><input type=submit value=Login>
</form>
'''
@app.route('/logout')
def logout():
# remove the username from the session if it's there
session.pop('username', None)
return redirect(url_for('index'))
Как сгенерировать хороший секретный ключ
Секретный ключ должен быть максимально случайным. Ваша операционная система имеет способы генерации довольно случайных данных на основе криптографического генератора случайных чисел. Используйте следующую команду для быстрого создания значения для Flask.secret_key (или SECRET_KEY):
$ python -c 'import secrets; print(secrets.token_hex())' '192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'
Примечание о сессиях на основе куки: Flask будет принимать значения, которые вы помещаете в объект сессии, и сериализовать их в куки. Если вы обнаружите, что некоторые значения не сохраняются между запросами, куки действительно включены, и вы не получаете ясного сообщения об ошибке, проверьте размер куки в ответах вашей страницы по сравнению с размером, поддерживаемым веб-браузерами.
Помимо стандартных сессий на стороне клиента, если вы хотите обрабатывать сессии на стороне сервера, существуют несколько расширений Flask, которые поддерживают это.
Сообщения всплывающего типа
Хорошие приложения и пользовательские интерфейсы основаны на обратной связи. Если пользователь не получает достаточной обратной связи, он, вероятно, возненавидит приложение. Flask предоставляет очень простой способ предоставления обратной связи пользователю с помощью системы всплывающего типа. Система всплывающего типа в основном позволяет записывать сообщение в конце запроса и получать к нему доступ в следующем (и только в следующем) запросе. Это обычно сочетается с шаблоном макета для отображения сообщения.
Чтобы отобразить сообщение всплывающего типа, используйте метод flash(), чтобы получить доступ к сообщениям, вы можете использовать get_flashed_messages(), который также доступен в шаблонах. См. Сообщения всплывающего типа для полного примера.
Ведение журнала
Журнал изменений
Добавлена в версии 0.3.
Иногда вы можете столкнуться с ситуацией, когда данные должны быть корректными, но на самом деле таковыми не являются. Например, у вас может быть некоторый код на стороне клиента, который отправляет HTTP-запрос на сервер, но он явно имеет неправильный формат. Это может быть вызвано тем, что пользователь изменяет данные или код клиента работает некорректно. В большинстве случаев в этой ситуации достаточно ответить 400 Bad Request, но иногда этого недостаточно, и код должен продолжать работать.
Вы всё равно можете вести журнал о том, что произошло что-то подозрительное. Именно здесь логгеры пригодятся. Начиная с Flask 0.3, для вас уже настроен логгер.
Вот несколько примеров вызовов логгера:
app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')
Прикреплённый logger — стандартный логгер Logger, поэтому обратитесь к официальной документации logging для получения дополнительной информации.
Включение WSGI-промежуточного ПО
Чтобы добавить WSGI-промежуточное ПО к вашему приложению Flask, оберните атрибут приложения wsgi_app. Например, чтобы применить промежуточное ПО Werkzeug ProxyFix для работы за Nginx:
from werkzeug.middleware.proxy_fix import ProxyFix app.wsgi_app = ProxyFix(app.wsgi_app)
Обертывание app.wsgi_app вместо app означает, что app всё ещё указывает на ваше приложение Flask, а не на промежуточное ПО, так что вы можете продолжить использование и настройку app напрямую.
Использование расширений Flask
Расширения — это пакеты, которые помогают выполнять распространённые задачи. Например, Flask-SQLAlchemy предоставляет поддержку SQLAlchemy, что упрощает и облегчает её использование с Flask.
Дополнительную информацию об расширениях Flask см. в разделе Расширения.
Развёртывание на веб-сервере
Готовы развернуть ваше новое приложение Flask? См. Развёртывание в продакшене.
© 2010 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/3.0.x/quickstart/