Что такое `flask.g` и как он используется в Flask?

Ответ

flask.g — это специальный объект в Flask, предназначенный для хранения данных, специфичных для текущего запроса. Он доступен на протяжении всего жизненного цикла обработки одного HTTP-запроса и позволяет передавать данные между различными функциями, хуками (before_request, after_request) и представлениями без использования глобальных переменных или передачи их через параметры.

Назначение: Основное назначение flask.g — предоставление временного хранилища для данных, которые должны быть доступны в разных частях приложения в рамках одного запроса, но не должны сохраняться между запросами. Это помогает избежать использования глобальных переменных, которые могут привести к проблемам с потокобезопасностью и состоянием.

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

from flask import Flask, g, request, jsonify

app = Flask(__name__)

# Предположим, у нас есть простая модель пользователя
class User:
    def __init__(self, name):
        self.name = name

def get_user_from_request(req):
    # В реальном приложении здесь была бы логика аутентификации
    # и получения пользователя из БД или сессии
    user_id = req.args.get('user_id')
    if user_id == '1':
        return User("Alice")
    return User("Guest")

@app.before_request
def before_request_hook():
    """
    Этот хук выполняется перед каждым запросом.
    Здесь мы можем загрузить пользователя и сохранить его в g.
    """
    g.user = get_user_from_request(request)
    print(f"User for this request: {g.user.name}")

@app.route('/')
def index():
    """
    В представлении мы можем легко получить доступ к g.user.
    """
    return f"Hello, {g.user.name}!"

@app.route('/profile')
def profile():
    return jsonify({"username": g.user.name, "message": "Welcome to your profile!"})

# Для запуска:
# if __name__ == '__main__':
#     app.run(debug=True)

Ключевые особенности и рекомендации:

  • Жизненный цикл: Данные, хранящиеся в g, существуют только в течение одного запроса. После завершения запроса объект g и его содержимое очищаются.
  • Потокобезопасность: flask.g является потокобезопасным, так как каждый поток (обрабатывающий отдельный запрос) имеет свою собственную копию g.
  • Не для постоянного хранения: g не предназначен для хранения данных между запросами (для этого используются сессии, базы данных или кэш).
  • Избегайте соединений с БД: Хотя технически можно хранить соединения с базой данных в g, для этого существуют более специализированные расширения Flask (например, Flask-SQLAlchemy), которые лучше управляют жизненным циклом соединений.
  • Удобство: Упрощает передачу контекстных данных (например, текущего пользователя, соединения с БД, конфигурации) между различными слоями приложения в рамках одного запроса.

Ответ 18+ 🔞

А, ну вот, смотри, этот flask.g — это такая, блядь, штука, как твой личный карман на время одной пьянки. Представь: ты пришёл в бар, один запрос — это одна вечеринка. И вот у тебя в кармане лежат ключи от дома, зажигалка и последняя сигарета. Ты можешь в любой момент залезть в этот карман, взять что надо, но как только ты вышел на улицу — всё, карман пустой, новая вечеринка, новые ключи, новая зажигалка. Понял, да?

Зачем это, на хуй, нужно? Чтобы не таскать эти самые ключи и зажигалку в руках по всему бару, сука, передавая их из одной руки в другую. Вместо того чтобы пихать данные через все функции как горячую картошку, ты просто кидаешь их в этот g и спокойно достаёшь, где тебе надо. И главное — у каждого гостя на этой вечеринке свой карман! Один чувак не полезет в карман другого, потокобезопасно, ёпта.

Смотри, как это выглядит в деле:

from flask import Flask, g, request, jsonify

app = Flask(__name__)

# Допустим, у нас есть пользователь, ну, типа, модель
class User:
    def __init__(self, name):
        self.name = name

# Функция, которая определяет, кто пришёл
def get_user_from_request(req):
    # В нормальном приложении тут бы был адский код с токенами и базой
    user_id = req.args.get('user_id')
    if user_id == '1':
        return User("Алиса")  # Ну, допустим, Алиса
    return User("Гость")  # А так — просто какой-то левый мудак

@app.before_request
def before_request_hook():
    """
    Эта штука срабатывает ПЕРЕД каждым запросом.
    Тут мы как раз и запихиваем нашего пользователя в карман `g`.
    """
    g.user = get_user_from_request(request)  # Вот, положили!
    print(f"На этой вечеринке у нас: {g.user.name}")

@app.route('/')
def index():
    """
    А в основном представлении мы просто достаём из кармана.
    Лепота, а не жизнь!
    """
    return f"Привет, {g.user.name}!"

@app.route('/profile')
def profile():
    # И здесь тоже достаём, нихуя не передавая
    return jsonify({"username": g.user.name, "message": "Добро пожаловать в профиль!"})

Важные моменты, чтобы не обосраться:

  • Одноразовый карман: Как только запрос обработан — всё, карман g вытряхивается. На следующий запрос он будет пустой. Не пытайся хранить там что-то навсегда, для этого есть сессии или база, ёпта.
  • Свой у каждого: У каждого запроса — свой объект g. Один поток не полезет в карман другого, это безопасно.
  • Не для всего подряд: Да, туда можно засунуть соединение с базой, но есть же специальные расширения, которые делают это красиво. Не изобретай велосипед, блядь.
  • Удобство — пиздец: Главная фишка — не таскать данные через всю цепочку вызовов. Положил в before_request — и потом в любой вьюхе, в любом хуке после запроса — просто берёшь и пользуешься. Красота, в рот меня чих-пых!

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