Функции flash и get_flashed_messages фреймворка Flask
В прошлом уроке мы научились возвращать данные обратно в форму. Это действие необходимо на случай, когда поля были заполнены не так, как надо. Теперь приступим к программированию проверки введенных данных. Будем проверять только адрес на его отсутствие в базе данных (страниц с одинаковыми адресами быть не должно) и наличие заголовка. Тело статьи у нас может быть пустым.
Начнем с заголовка. Если страница запрошена методом POST и содержимое поля h1 равно пустой строке, то при загрузке страницы, помимо возврата данных в форму, необходимо сообщить пользователю, что он сделал не так. И здесь на помощь приходит функция flash
модуля flask
(предварительно ее надо импортировать).
@app.route('/', methods=['GET', 'POST']) def index(): if request.method == 'POST': if request.form['h1'] == '': flash('Пропущен заголовок!') return render_template('create.html', sections=sections)
При этом будет возникать ошибка, так как для вызова flash()
нужен секретный ключ. Поэтому после строки создания объекта Flask
следует его добавить.
app = Flask(__name__) app.config['SECRET_KEY'] = 'enter your key'
В шаблоне перед формой добавим контейнер для вывода сообщений:
{% for message in get_flashed_messages() %} <p style="color:red;text-align:center">{{ message }}</p> {% endfor %}
Функция get_flashed_messages()
возвращает все flash-сообщения, которые были сгенерированы и накоплены при выполнении скрипта.
Чтобы проверить путь на уникальность, надо выполнить соответствующий запрос к базе данных, и если записи с таким адресом не найдется, признать его допустимым. Пути хранятся в колонке path таблицы articles. Запросим запись, в которой path равен тому, что ввел пользователь в поле формы.
Проверка будет считаться пройденной, если такой записи не найдется.
def test_path(path): c = sqlite3.connect(db_name) p = c.execute('SELECT * FROM articles WHERE path=?', (path, )).fetchone() c.close() return p is None @app.route('/', methods=['GET', 'POST']) def index(): if request.method == 'POST': if request.form['h1'] == '': flash('Пропущен заголовок!') elif request.form['path'] == '': flash('Строка адреса пуста!') elif not test_path(request.form['path']): flash('Страница с таким адресом уже есть!') else: # Запись статьи в базу данных (не реализовано) # Перенаправление на только что созданную страницу (не реализовано) flash('Страница создана!') return render_template('create.html', sections=sections)
Перед этим также следует проверять на отсутствие пустоты в строке адреса. В нашем случае записи в БД с адресом главной страницы не будет.
После того, как все проверки успешно пройдены, статья должна записываться в базу данных. Кроме того, мы будем перенаправлять пользователя на эту страницу. При этом вспомним, что в нашем проекте есть две разных python-программы. Первая ‒ "пользовательская" для отображения статей. Вторая, над которой сейчас работаем, ‒ для их создания и редактирования.
Поэтому при перенаправлении на страницу статьи в ней будет также открываться форма. Поля формы при открытии страницы будут заполнены данными соответствующей статьи из базы данных.
Все это немного отличается от того, как принято в популярных системах управления контентом (CMS). В них при нажатии на кнопку "Сохранить", вас перенаправляет по адресу статьи, где она предстает в готовом опубликованном виде. Если надо ее править, то тут же есть кнопка "Правка", при нажатии на которую открывается форма для редактирования статьи. Адреса страницы с формой для правки и самой страницы отличаются.
Мы могли бы разрабатывать flask-приложение для администратора подобным образом. Однако будет проще запускать на одном локальном сервере два приложения. В одном смотреть, как выглядят страницы в готовом виде, в другом ‒ выполнять правку сайта. Когда сайт будет работать на удаленном веб-сервере, то второе приложение там не нужно. После правки базы данных на локальном сервере, нужно будет копировать ее на удаленный, где она перезапишет старую версию. Или в скрипте admin.py сразу настроить подключение к удаленной базе данных (не вариант в случае использования SQLite).
Пока вернемся к функции flash
и обратим внимание на то, что сообщения в случае неверного заполнения формы выводятся красным цветом. Хорошо бы при положительном исходе выводить фразу "Страница создана!" каким-нибудь другим цветом, например, зеленым. Это легко реализовать, так как flash
предусматривает возможность передачи второго аргумента, который играет роль категории сообщения (вы их придумываете сами).
if request.form['h1'] == '': flash('Пропущен заголовок!', 'error') elif request.form['path'] == '': flash('Строка адреса пуста!', 'error') elif not test_path(request.form['path']): flash('Страница с таким адресом уже есть!', 'error') else: # Запись статьи в базу данных (не реализовано) # Перенаправление на только что созданную страницу (не реализовано) flash('Страница создана!', 'success')
В шаблоне категория может использоваться как имя класса:
{% block styles_scripts %} <style> .error { color: red; text-align: center; } .success { color: green; text-align: center; } </style> {% endblock %} ... {% for category, message in get_flashed_messages(with_categories=true) %} <p class="{{ category }}">{{ message }}</p> {% endfor %}
В данном случае необходимо при вызове функции get_flashed_messages
установить параметр with_categories
в значение true
.