Как сохранить настройки чекбоксов в 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-поле: используйте булевы значения или словари. Проверяйте, что в шаблон передаётся структура, которую можно итерировать или обращаться по ключу. Это избавит от проблем с отображением и сделает код надёжнее.

    Часто задаваемые вопросы