Сессии, вход и страницы ошибок
HTTP «забывчив»: каждый запрос сервер обрабатывает с нуля и не знает, кто его прислал. Чтобы помнить посетителя — его корзину, счётчик, вход на сайт, — нужны сессии.
Session
from flask import Flask, session
app = Flask(__name__)
app.secret_key = "длинная-случайная-строка"
@app.route("/")
def index():
session["visits"] = session.get("visits", 0) + 1
return f"Вы здесь в {session['visits']}-й раз"
session работает как словарь, но у каждого посетителя он свой. Flask хранит его в cookie браузера и подписывает ключом secret_key: посетитель может cookie прочитать, но подделать — нет.
session.get(ключ, по_умолчанию),session[ключ] = значение;session.pop(ключ, None)— удалить ключ,session.clear()— очистить всё;- в настоящем проекте
secret_key— длинная случайная строка (python -c "import secrets; print(secrets.token_hex())"), и хранят её не в коде, а в переменной окружения.
Глобальные переменные в коде — общие для всех посетителей. В них можно хранить данные сайта (список проектов, сообщения), но не данные конкретного человека.
Вход на сайт
import hmac
@app.route("/login", methods=["POST"])
def login():
if hmac.compare_digest(request.form.get("password", ""), PASSWORD):
session["admin"] = True
return redirect(url_for("admin"))
return "Неверный пароль", 401
@app.route("/admin")
def admin():
if session.get("admin") is not True:
return redirect(url_for("login"))
return "Панель владельца"
hmac.compare_digestсравнивает строки за одинаковое время, и злоумышленник не может по скорости ответа угадывать пароль по символу;- проверяйте значение, а не наличие ключа:
"admin" in sessionистинно и дляsession["admin"] = False; - в настоящих проектах пароль хранят не открытым текстом, а в виде хеша (
werkzeug.security.generate_password_hash), а для пользователей берут готовые расширения вроде Flask-Login.
Свои страницы ошибок
@app.errorhandler(404)
def not_found(e):
if request.path.startswith("/api/"):
return {"error": "not found"}, 404
return render_template_string("<h1>Страница не найдена</h1>"), 404
Обработчик вызывается для любого неизвестного адреса и для abort(404). Код нужно вернуть явно — иначе ответ уйдёт с кодом 200, и поисковики решат, что страница существует. Так же делаются обработчики для 500 и других кодов.
Что дальше
Готовый сайт выкладывают на хостинг (Render, PythonAnywhere, свой сервер). Там его запускают не через app.run, а через сервер вроде gunicorn или waitress: waitress-serve --port=8000 app:app. Данные хранят в базе — например, SQLite через расширение Flask-SQLAlchemy.
Итог
secret_keyиsession— свои данные у каждого посетителя;- вход:
hmac.compare_digest,session["admin"] is True, перенаправление гостей; @app.errorhandler(404)— свой ответ, но с правильным кодом;- глобальные переменные — общие для всех.