### app_context
Используется для доступа к экземпляру приложения вне запроса. Он позволяет получить доступ к конфигурации приложения, расширениям Flask и другим объектам, которые доступны только на этапе создания приложения.
Чтобы использовать app_context в Flask, вам нужно создать экземпляр приложения, а затем создать контекст приложения с помощью метода app.app_context(). После этого вы можете выполнять любой код, который требует доступа к экземпляру приложения.
```
from flask import Flask
app = Flask(__name__)
app.config['DEBUG'] = True
with app.app_context():
# Выполнение кода, который требует доступа к экземпляру приложения
print(app.config['DEBUG'])
```
Вы также можете использовать app_context в функции Flask, чтобы получить доступ к экземпляру приложения, например, так:
```
from flask import Flask, current_app
app = Flask(__name__)
@app.route('/')
def index():
app = current_app._get_current_object()
# Выполнение кода, который требует доступа к экземпляру приложения
return 'Hello World!'
```
### Декоратор before_first_request
Позволяет определить функцию, которая будет выполнена перед обработкой первого запроса. Это может быть полезно, если вам нужно выполнить какую-то инициализацию перед запуском приложения.
```
from flask import Flask
app = Flask(__name__)
@app.before_first_request
def init_app():
# выполнение инициализации приложения перед первым запросом
print('Application initialized.')
@app.route('/')
def index():
return 'Hello, world!'
if __name__ == '__main__':
app.run()
```
### Метод log_exception
Используется для логирования исключений, возникших во время обработки запроса. Этот метод вызывается автоматически, если происходит исключение во время выполнения запроса.
log_exception принимает три аргумента: тип исключения exc_info, который представляет кортеж из трех значений (тип, значение и трассировку стека); имя функции function_name, в которой возникло исключение, и информацию о запросе request.
```
from flask import Flask, request
import logging
app = Flask(__name__)
@app.route('/')
def index():
return 1/0
@app.after_request
def after_request(response):
if response.status_code != 500:
return response
app.logger.error('Unhandled Exception: %s', (exc_info := request.exc_info))
return response
if __name__ == '__main__':
logging.basicConfig(filename='app.log', level=logging.DEBUG)
app.run(debug=True)
```
### Функция make_aborter
Позволяет создавать персонализированные объекты HTTPException, которые могут использоваться для прерывания обработки запроса и возвращения соответствующего HTTP-статуса кода и сообщения об ошибке.
make_aborter принимает словарь, в котором каждый ключ соответствует коду ошибки HTTP, а значение - пользовательскому сообщению об ошибке, которое будет возвращено вместе со статусом кодом при вызове объекта HTTPException.
Вот пример использования make_aborter для создания объекта HTTPException с пользовательским сообщением об ошибке:
```
from flask import Flask, abort, make_response, jsonify
app = Flask(__name__)
error_messages = {
400: 'Bad Request',
401: 'Unauthorized',
403: 'Forbidden',
404: 'Not Found',
500: 'Internal Server Error'
}
aborter = make_aborter(error_messages)
@app.route('/')
def index():
aborter(404)
if __name__ == '__main__':
app.run(debug=True)
```
### make_response
Позволяет создавать объект Response для ответа на запрос. Она принимает три аргумента:
* response: объект, который будет использоваться в качестве ответа на запрос. Это может быть строка, объект jsonify, объект render_template, файл и т.д.
* status: HTTP-статус код, который будет возвращен вместе с ответом на запрос. По умолчанию это 200 (OK).
* headers: список заголовков HTTP, которые будут добавлены к ответу на запрос. Это может быть словарь с ключами и значениями заголовков, или список кортежей, где каждый кортеж представляет собой заголовок и его значение.
```
from flask import Flask, jsonify, make_response
app = Flask(__name__)
@app.route('/')
def index():
data = {'message': 'Hello, World!'}
response = jsonify(data)
response.headers['Content-Type'] = 'application/json'
return make_response(response, 200)
if __name__ == '__main__':
app.run(debug=True)
```
### Декоратор process_response
Позволяет обрабатывать ответы на запросы перед тем, как они будут отправлены клиенту.
Функция, которая будет использоваться в качестве обработчика, должна принимать два аргумента: response и request. response - это объект Response, который будет отправлен клиенту, а request - объект Request, который был использован для отправки запроса.
```
from flask import Flask, Response, request
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello, World!'
@app.after_request
def add_header(response):
response.headers['X-My-Header'] = 'Custom Header'
return response
if __name__ == '__main__':
app.run(debug=True)
```
### Декоратор teardown_appcontext
Регистрирует функцию, которая будет вызываться после завершения обработки запроса и передачи управления объекту контекста приложения.
Контекст приложения - это объект, который хранит состояние приложения, доступное в рамках текущего запроса. Он содержит информацию, такую как база данных, авторизация пользователя, конфигурация приложения и многое другое.
Декоратор teardown_appcontext позволяет зарегистрировать функцию, которая будет выполняться после завершения обработки запроса и передачи управления объекту контекста приложения. Это может быть полезно для выполнения дополнительных задач, таких как закрытие соединения с базой данных или удаление временных файлов.
```
from flask import Flask, g, request
app = Flask(__name__)
app.config['DATABASE'] = 'path/to/database'
def get_db():
if not hasattr(g, 'db'):
g.db = connect_to_database(app.config['DATABASE'])
return g.db
@app.teardown_appcontext
def close_db(exception):
db = getattr(g, 'db', None)
if db is not None:
db.close()
@app.route('/')
def index():
db = get_db()
# делаем запросы к базе данных
return 'Hello, World!'
if __name__ == '__main__':
app.run(debug=True)
```
### Метод do_teardown_request
Вызывается после того, как запрос был обработан и ответ был отправлен клиенту.
Этот метод выполняет некоторые действия по очистке, завершению и закрытию объектов, которые были созданы во время обработки запроса. Например, он закрывает соединения с базой данных, которые были открыты во время обработки запроса.
Встроенные функции Flask обычно автоматически вызывают do_teardown_request, но если вам нужно выполнить какие-то дополнительные действия после завершения запроса, вы можете зарегистрировать функцию с помощью декоратора @app.teardown_request.
```
from flask import Flask, g, request
app = Flask(__name__)
app.config['DATABASE'] = 'path/to/database'
def get_db():
if not hasattr(g, 'db'):
g.db = connect_to_database(app.config['DATABASE'])
return g.db
@app.teardown_request
def close_db(exception=None):
db = getattr(g, 'db', None)
if db is not None:
db.close()
@app.route('/')
def index():
db = get_db()
# делаем запросы к базе данных
return 'Hello, World!'
if __name__ == '__main__':
app.run(debug=True)
```
### Метод teardown_appcontext
Вызывается после завершения работы приложения, когда контекст приложения больше не нужен.
Этот метод может быть использован для выполнения некоторых действий по завершению работы приложения. Например, он может закрыть соединения с базой данных, завершить сессии пользователей, удалить временные файлы и т.д.
Вы можете зарегистрировать функцию, которая будет вызываться после завершения работы приложения, с помощью декоратора @app.teardown_appcontext. Пример:
```
from flask import Flask
app = Flask(__name__)
@app.teardown_appcontext
def cleanup_db(exception):
# закрыть соединение с базой данных
db_session.close()
if __name__ == '__main__':
app.run(debug=True)
```
Чтобы установить заголовки ответа для всех маршрутов и представлений в приложении Flask, вы можете использовать декоратор after_request. Декоратор after_request регистрирует функцию, которая вызывается после того, как запрос был обработан и готов к отправке ответа.
```
from flask import Flask, jsonify
app = Flask(__name__)
@app.after_request
def add_headers(response):
response.headers['X-Content-Type-Options'] = 'nosniff'
response.headers['X-Frame-Options'] = 'SAMEORIGIN'
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains; preload'
response.headers['X-XSS-Protection'] = '1; mode=block'
response.headers['Referrer-Policy'] = 'no-referrer-when-downgrade'
response.headers['Content-Type'] = 'text/html; charset=utf-8'
return response
@app.route('/')
def index():
data = {'message': 'Hello, World!'}
return jsonify(data)
if __name__ == '__main__':
app.run()
```
## Bleuprints
Что что можно применять к приложению можно и применить к конкретному blueprint-у
## Метод after_app_request
Позволяет зарегистрировать функцию, которая будет вызываться после того, как запрос был обработан приложением.
Этот метод работает аналогично глобальному after_request методу приложения Flask, но он применяется только к маршрутам, зарегистрированным в данном Blueprint.
Вы можете использовать метод after_app_request для выполнения каких-либо действий после завершения запроса, например, для логирования или сохранения данных. Функция, которую вы зарегистрируете с помощью after_app_request, должна принимать объект ответа Flask и возвращать его без изменений.
```
from flask import Flask, Blueprint
app = Flask(__name__)
bp = Blueprint('my_blueprint', __name__)
@bp.route('/hello')
def hello():
return 'Hello, World!'
def after_request(response):
# Do some logging or processing with the response object
return response
bp.after_app_request(after_request)
app.register_blueprint(bp)
if __name__ == '__main__':
app.run(debug=True)
```
### Метод before_request
Позволяет зарегистрировать функцию, которая будет вызываться перед тем, как запрос будет обработан приложением.
Этот метод работает аналогично глобальному before_request методу приложения Flask, но он применяется только к маршрутам, зарегистрированным в данном Blueprint.
Вы можете использовать метод before_request для выполнения каких-либо действий перед обработкой запроса, например, для проверки аутентификации пользователя или для установки контекста приложения. Функция, которую вы зарегистрируете с помощью before_request, может принимать произвольное число аргументов, но она должна вернуть None или объект ответа Flask.
```
from flask import Flask, Blueprint, request, abort
app = Flask(__name__)
bp = Blueprint('my_blueprint', __name__)
@bp.route('/hello')
def hello():
return 'Hello, World!'
def before_request():
if request.headers.get('X-Secret-Key') != 'my-secret-key':
abort(401)
bp.before_request(before_request)
app.register_blueprint(bp)
if __name__ == '__main__':
app.run(debug=True)
```
## Полезные функции
### Декоратор after_this_request
Позволяет добавить функцию, которая будет вызвана после того, как будет сформирован ответ на текущий запрос. Это может быть полезно, если вы хотите выполнить какое-то действие после того, как ответ был отправлен клиенту.
```
@app.route('/')
def index():
@after_this_request
def add_header(response):
response.headers['X-Foo'] = 'Parachute'
return response
return 'Hello World!'
```
### функция stream_with_context
Позволяет создать контекстный менеджер для потока, связанного с запросом.
При работе с запросами, которые возвращают большие объемы данных, может возникнуть необходимость поэтапной отправки данных клиенту. Например, если вы отправляете файл размером несколько гигабайт, вы не хотите дожидаться полной загрузки файла на сервере, прежде чем начать отправку данных клиенту.
Для этого вы можете использовать функцию stream_with_context, которая позволяет считывать данные из файла по частям и отправлять их в виде потока.
```
from flask import Flask, Response, stream_with_context
app = Flask(__name__)
@app.route('/download')
def download():
def generate():
with open('largefile.csv', 'r') as f:
while True:
chunk = f.read(1024)
if not chunk:
break
yield chunk
response = Response(stream_with_context(generate()))
response.headers.set('Content-Disposition', 'attachment', filename='largefile.csv')
response.headers.set('Content-Type', 'text/csv')
return response
```