Как сохранить настройки чекбоксов в Flask и SQLAlchemy
При разработке веб-приложений на Flask часто возникает задача сохранения пользовательских настроек, например, состояния чекбоксов. В этой статье разберём типичную ошибку, когда данные из формы не отображаются в шаблоне, хотя в Python всё сохраняется корректно. Мы рассмотрим правильный способ работы с JSON-полями в SQLAlchemy и передачу данных в Jinja2.
Почему чекбоксы не отображаются в шаблоне?
Основная причина - неправильная структура данных, сохраняемых в поле acc_settings. В примере используется список строк вида ['checked=on', 'Null', ...], но шаблон ожидает либо словарь, либо список с булевыми значениями. При итерации по такому списку в Jinja2 условие {{ old_settings[0] }} не срабатывает, так как значение - строка, а не атрибут HTML.
Правильная структура JSON для настроек
Лучше хранить настройки в виде словаря или списка булевых значений. Например:
- Словарь:
{'invis_1': True, 'invis_2': False} - Список:
[True, False, True]
Это упрощает проверку в шаблоне и делает код более читаемым.
Исправляем модель SQLAlchemy
Оставьте поле acc_settings как JSON, но при сохранении формируйте корректную структуру. Пример:
get_us.acc_settings = {'invis_1': bool(request.form.get('invis_1_bt')), 'invis_2': bool(request.form.get('invis_2_bt'))}Обновляем шаблон Jinja2
В HTML используйте условие на основе булевого значения:
<input type='checkbox' name='invis_1_bt' {% if old_settings['invis_1'] %}checked{% endif %}>Если храните список - проверяйте по индексу: {% if old_settings[0] %} ... {% endif %}. Убедитесь, что в Python вы передаёте именно список, а не строку.
Частые ошибки при работе с JSON в Flask
- Сохранение строк вместо булевых значений - используйте
bool()илиTrue/False. - Неправильная сериализация - SQLAlchemy сам сериализует JSON, не нужно вызывать
json.dumps(). - Отсутствие проверки ключа - при обращении к словарю используйте
.get(), чтобы избежать ошибок.
Пример рабочего решения
Ниже приведён исправленный код для маршрута settings_accept:
@app.route('/login/settings_accept', methods=['POST', 'GET'])
def settings_accept():
if check_acc(request.cookies.get('login'), request.cookies.get('password')):
get_us = get_user_login(request.cookies.get('login'), request.cookies.get('password'))
settings = {}
for i in range(1, 11):
key = f'invis_{i}_bt'
settings[key] = bool(request.form.get(key))
get_us.acc_settings = settings
db.session.commit()
return redirect('/login/settings')
return redirect('/login')После этого в шаблоне вы сможете обращаться к old_settings['invis_1_bt'] и получать True или False, что корректно отработает в условии checked.
Заключение
Чтобы чекбоксы корректно отображались в Flask, следите за типом данных при сохранении в JSON-поле: используйте булевы значения или словари. Проверяйте, что в шаблон передаётся структура, которую можно итерировать или обращаться по ключу. Это избавит от проблем с отображением и сделает код надёжнее.