До этого в уроках мы создавали очень простые страницы. Браузер направляет запрос серверу, который в ответ отправляет HTML-страницу, и на этом процесс заканчивается. HTTP — это протокол без состояния, что означает отсутствие встроенных средств для идентификации пользователя при повторных запросах. Сервер обрабатывает каждого пользователя так, словно он впервые обращается к странице.
Однако если зайти, например, на сайт интернет-магазина и выполнить поиск, то в следующий раз сайт предложит рекомендации, основанные на предыдущих действиях. В чем секрет?
Все дело в куки и сессиях.
Этот урок посвящен куки, а тема сессий будет разобрана в следующем.
Что такое куки?
Куки представляют собой данные, которые сервер сохраняет в браузере. Процесс работы с ними выглядит так:
- Браузер запрашивает у сервера веб-страницу.
- Сервер отправляет эту страницу обратно, возможно, сопровождая ее одним или несколькими куки.
- Браузер отображает страницу и сохраняет куки на устройстве пользователя.
- При дальнейших запросах браузер включает данные из куки в заголовок Cookie, пока срок действия куки не истечет и они не будут удалены.
Настройка куки
Во Flask для установки куки используется метод set_cookie()
объекта ответа. Его синтаксис:
set_cookie(key, value="", max_age=None)
key — это название куки, обязательный параметр. value — данные для сохранения, по умолчанию это пустая строка. max_age — срок действия в секундах. Если его не указать, куки сохранятся до закрытия браузера.
Давайте откроем main2.py для добавления следующего кода после функции представления contact()
:
from flask import Flask, render_template, request, redirect, url_for, flash, make_response #... @app.route('/cookie/') def cookie(): res = make_response("Setting a cookie") res.set_cookie('foo', 'bar', max_age=60*60*24*365*2) return res #...
Этот код создает куки с именем foo и значением bar сроком действия в 2 года.
Запустив сервер и открыв http://localhost:5000/cookie/
в браузере, вы увидите сообщение “Setting a cookie”
.
Чтобы проверить настроенные сервером куки, в браузере Firefox можно открыть инспектор хранилища, нажав Shift+F9. В появившемся окне выберите "Cookies" слева и нажмите http://localhost:5000/
для просмотра всех сохраненных куки.
Отныне куки foo передаются в каждом запросе к http://localhost:5000/
. Это можно проверить в сетевом мониторе Firefox, который вызывается сочетанием клавиш Ctrl+Shift+E.
В открывшемся окне выберите первый запрос слева, чтобы увидеть детали на правой панели.
Важно: если куки уже настроены, каждый запрос к http://localhost:5000/cookie/
обновляет срок их действия.
Доступ к куки
Для получения доступа к куки используется атрибут cookie в объекте request. cookie — это словарь, содержащий все куки от браузера.
Изменим функцию cookie()
в файле main2.py следующим образом:
#... @app.route('/cookie/') def cookie(): if not request.cookies.get('foo'): res = make_response("Setting a cookie") res.set_cookie('foo', 'bar', max_age=60*60*24*365*2) else: res = make_response("Value of cookie foo is {}".format(request.cookies.get('foo'))) return res #...
Теперь функция проверяет наличие куки и отображает их значение, если они существуют. В противном случае куки создаются заново.
Перейдя сейчас на http://localhost:5000/cookie/
, страница отобразит текущее значение куки.
Объект request доступен и в шаблонах, что позволяет получать доступ к куки с помощью Python в шаблонах. Подробности будут раскрыты в следующих частях.
Удаление куки
Чтобы удалить куки, применяется метод set_cookie()
с указанием имени куки и значением max_age=0
. Код для удаления можно добавить в main2.py после функции cookie()
.
#... @app.route('/delete-cookie/') def delete_cookie(): res = make_response("Cookie Removed") res.set_cookie('foo', 'bar', max_age=0) return res #...
При посещении http://localhost:5000/delete-cookie/
пользователь увидит следующее сообщение:
Теперь, когда вы знаете, как работают куки, можно перейти к изучению практических примеров кода, чтобы освоить их настройку для хранения пользовательских предпочтений.
Добавьте следующий код после функции delete_cookie()
в main2.py.
#... @app.route('/article/', methods=['POST', 'GET']) def article(): if request.method == 'POST': print(request.form) res = make_response("") res.set_cookie("font", request.form.get('font'), 60*60*24*15) res.headers['location'] = url_for('article') return res, 302 return render_template('article.html') #...
Теперь создадим новый файл article.html с таким содержимым:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Article</title> </head> <body style="{% if request.cookies.get('font') %}font-family:{{ request.cookies.get('font') }}{% endif %}"> Select Font Preference: <br> <form action="" method="post"> <select name="font" onchange="submit()"> <option value="">----</option> <option value="consolas" {% if request.cookies.get('font') == 'consolas' %}selected{% endif %}>consolas</option> <option value="arial" {% if request.cookies.get('font') == 'arial' %}selected{% endif %}>arial</option> <option value="verdana" {% if request.cookies.get('font')== 'verdana' %}selected{% endif %}>verdana</option> </select> </form> <h1>Festus, superbus toruss diligenter tractare de brevis, dexter olla.</h1> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam blanditiis debitis doloribus eos magni minus odit, provident tempora. Expedita fugiat harum in incidunt minus nam nesciunt voluptate. Facilis nesciunt, similique!</p> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias amet animi aperiam inventore molestiae quos, reiciendis voluptatem. Ab, cum cupiditate fugit illo incidunt ipsa neque quam, qui quidem vel voluptatum.</p> </body> </html>
При первоначальном посещении http://localhost:5000/article
страница будет отображаться с шрифтом по умолчанию.
Если выбрать другой шрифт через выпадающее меню, форму отправится, и куки font с новым значением будут обновлены на 15 дней. Пользователь перенаправится обратно на страницу http://localhost:5000/article
, уже с выбранным шрифтом.
При повторном посещении страницы http://localhost:5000/article
она будет отображаться с тем шрифтом, который был выбран ранее.
Таким образом, после выбора нового шрифта, страница обновится и отобразит содержимое в новом стиле.
Недостатки куки
Перед внедрением куки в проект следует помнить о некоторых их недостатках.
- Куки не считаются безопасными. Данные в них доступны всем, поэтому не следует хранить в куки пароли, информацию о банковских картах и другие важные данные.
- Пользователи могут отключить куки. Большинство браузеров позволяют деактивировать куки, при этом никакого предупреждения не предоставляется. Решить проблему можно простейшим кодом на JavaScript, который будет уведомлять пользователя о необходимости включить куки для корректной работы сайта.
<script> document.cookie = "foo=bar;"; if (!document.cookie) { alert("This website requires cookies to function properly"); } </script>
- Объем каждого куки ограничен 4 КБ, а количество куки, которое может сохранить сайт, также ограничено — обычно от 30 до 50.
- Куки передаются серверу в каждом запросе. Если использовать 20 куки по 4 КБ на сайте, это значит, что каждый запрос увеличится на 80 КБ данных.
Часть из этих недостатков можно устранить, используя сессии, которые будут рассмотрены в следующем уроке.