Почему фляга требует перенаправления после POST?

У меня есть массив форм, которые я хочу отобразить в виде колбы, называемой вентиляторами. Я использую sqlalchemy для SQLLite во время разработки, чтобы сохранить данные и flask-wtforms для рендеринга. Похоже, проблема связана с DecimalRangeField: если у меня есть два или более вентилятора и я меняю ползунок только на одном, другой ползунок перемещается в соответствии с ним, несмотря на то, что значение данных DecimalRangeField остается неизменным. Примечание. Код ниже работает, проблема возникает, когда удаляется строка перенаправления, которую я выделил ниже.

Вот код Routes.py с добавленным «исправлением» перенаправления:

@bp.route('/', methods=['GET', 'POST'])
def fans_index():
    fans = Fan.query.all()
    if fans.__len__() == 0:
      return redirect(url_for('fans.newfan'))
    form = FanForm(request.form)
    if form.validate_on_submit(): # request.method == 'POST'
      for fan in fans:
        if fan.name == form.name.data:
          fan.swtch = form.swtch.data
          fan.speed = round(form.speed.data)
          db.session.commit()
      return redirect(url_for('fans.fans_index')) # <-- THIS is required, why?
    else: # request.method == 'GET'
      pass
    forms = []
    for fan in fans:
      form = FanForm()
      form.name.data = fan.name
      form.swtch.data = fan.swtch
      form.speed.data = fan.speed
      forms.append(form)
    return render_template('fans_index.html', title='Fans!', forms=forms)

Вот используемая форма:

class FanForm(FlaskForm):
    name = HiddenField('Name')
    swtch = BooleanField('Switch', render_kw = {'class': 'swtch'})
    speed = DecimalRangeField('Speed', render_kw = {'class': 'speed'}, validators=[DataRequired()])
    submit = SubmitField('Save Fan')

А вот html-шаблон:

<h1>Fans</h1>
<div class = "container">
    <div class = "row">
        {% for form in forms %}
        <div class = "col mx-1 shadow-5-strong border border-white rounded" style = "max-width: 220px">
            <h2 class = "ms-1">{{ form.name.data }}:</h2>
            <form class = "mx-auto ms-3" name = "{{ form.name.data }}" action = "" method = "post">
                {{ form.hidden_tag() }}
                <div>{{ form.name }}</div> 
                <p>
                    {{ form.speed.label }}: <span class = "speed_display_val">{{ form.speed.data | round }}%</span><br>
                    {{ form.speed(min=20) }}<br>
                    {% for error in form.speed.errors %}
                    <span style = "color: red;">[{{ error }}]</span>
                    {% endfor %}
                </p>
                <p>
                  {{ form.swtch.label }} <span class = "ms-3">{{ form.swtch }}</span><br>
                  {% for error in form.swtch.errors %}
                  <span style = "color: red;">[{{ error }}]</span>
                  {% endfor %}
                </p>
                <p>{{ form.submit }}</p>
            </form>
        </div>
        {% endfor %}
    </div>
</div>

У меня также есть простой javascript для этой страницы, который анимирует слайдер и отправляет сообщения, когда пользователь перемещает ползунок или устанавливает флажок для включения и выключения вентиляторов:

/* script to animate the slider value changing and post data on slider mouseup or switch click */
const values = Array.from(document.getElementsByClassName('speed_display_val'));
const speeds = Array.from(document.getElementsByClassName('speed'));
const swtches = Array.from(document.getElementsByClassName('swtch')); //Note: switch is a reserved word in JS

speeds.forEach((speed, i) => {
  speed.oninput = (e) => { values[i].textContent = Math.round(e.target.value) + '%' };
  speed.onmouseup = () => { speed.form.requestSubmit() };
});
swtches.forEach((swtch) => {
  swtch.onclick = () => { swtch.form.requestSubmit() };
});
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
142
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

FlaskForm автоматически будет использовать значения из flask.request.form и flask.request.files. Чтобы обойти эту проблему, вы можете передать None в качестве атрибута formdata формы. Таким образом, перенаправление, которое сбрасывает flask.request.form, больше не требуется.

Тогда ваш код будет выглядеть примерно так.

@bp.route('/', methods=['GET', 'POST'])
def fans_index():
    if Fan.query.count() == 0:
        return redirect(url_for('.newfan'))
    
    form = FanForm(request.form)
    if form.validate_on_submit():
        if fan := Fan.query.filter_by(name=form.name.data).first():
            fan.swtch = form.swtch.data
            fan.speed = round(form.speed.data)
            db.session.commit()

    forms = [FanForm(formdata=None, obj=fan) for fan in Fan.query.all()]
    return render_template('fans_index.html', **locals())

Отличный. Вы объяснили, почему это не работает, и не только предоставили рабочий код, но и несколько других примеров более питонических способов сделать то же самое, что я пытался сделать. Как человек с многолетним опытом программирования, но новичок в Python, я ценю это.

dmcgrandle 09.07.2024 21:44

Другие вопросы по теме