更新表单验证同一页面上的其他表单而不是她自己(Flask)

Update form validates the other form on same page instead of herself (Flask)

我是 Flask 的新手,正在使用它创建我的第一个项目。我试图在同一页面上获取一些表格:上面用于创建会议的表格和 bootstrap 模态(更新、删除)中的其他 2 个表格,用于 table 中的每一行。创建表单和删除表单工作正常,但问题是当我使用更新表单时。我想在表单中包含 object 中的值,以便轻松更新它们。我不知道为什么,但是当我尝试更新会议并点击提交(“保存更改”)时,表单会使用更新表单中的值提交“create_form”。有趣的是,我得到了创建用户的另一个页面(相同的方法 - 3 种形式(2 种带有模态)和 .validate_on_submit 在同一路线),并且一切正常(更新形式不提交创建表格)。我认为 .validate_on_submit() 足以区分这两种形式的用法,但现在我很困惑。我应该分离代码,并为更新和删除创建新的路由,还是还有其他事情要做?

这是代码。

路线:

@creator.route('/meetings', methods=['GET', 'POST'])
@login_required
@usertype_required('coach')
def meetings_page():
    meetings = Meeting.query.order_by(Meeting.date).all()
    create_meeting_form = CreateMeetingForm()
    update_meeting_form = UpdateMeetingForm()
    delete_meeting_form = DeleteForm()

    if create_meeting_form.validate_on_submit():
        meeting_to_create = Meeting(date=create_meeting_form.date.data,
                                    hour=str(create_meeting_form.hour.data)[:5],
                                    day=weekdays_tuple[create_meeting_form.date.data.weekday()],
                                    type=create_meeting_form.type.data,
                                    locality=create_meeting_form.locality.data,
                                    pitch=create_meeting_form.pitch.data)
        db.session.add(meeting_to_create)
        db.session.commit()
        flash("Meeting created successfully!", category='info')
        return redirect(url_for('creator.meetings_page'))

    if update_meeting_form.validate_on_submit():
        meeting_to_update = request.form.get('update_meeting')
        update_meeting = Meeting.query.filter_by(meeting_id=meeting_to_update).first()
        if update_meeting:
            update_meeting.date = update_meeting_form.date.data
            update_meeting.hour = str(update_meeting_form.hour.data)[:5]
            update_meeting.pitch = update_meeting_form.pitch.data
            update_meeting.locality = update_meeting_form.locality.data
            update_meeting.type = update_meeting_form.type.data
            db.session.commit()
            flash("Changed meeting info!", category='info')
            return redirect(url_for('creator.meetings_page'))

    if delete_meeting_form.validate_on_submit():
        meeting_to_delete = request.form.get('delete_meeting')
        del_meeting = Meeting.query.filter_by(meeting_id=meeting_to_delete).first()
        if del_meeting:
            db.session.delete(del_meeting)
            db.session.commit()
            flash("Deleted meeting successfully!", category='info')
            return redirect(url_for('creator.meetings_page'))

    return render_template('creator/meetings.html',
                           create_meeting_form=create_meeting_form,
                           update_form=update_meeting_form,
                           delete_form=delete_meeting_form,
                           meetings=meetings)

模板:

{% block content %}
<div class="container">
    <form method="POST" class="form-control">
        {{ create_meeting_form.csrf_token }}
        
        {{ create_meeting_form.date.label }}
        {{ create_meeting_form.date(class="form-control") }}
        <br/>
        {{ create_meeting_form.hour.label }}
        {{ create_meeting_form.hour(class="form-control") }}
        <br/>
        {{ create_meeting_form.locality.label }}
        {{ create_meeting_form.locality(class="form-control") }}
        <br/>
        {{ create_meeting_form.type.label }}
        {{ create_meeting_form.type(class="form-control") }}
        <br/>
        {{ create_meeting_form.pitch.label }}
        {{ create_meeting_form.pitch(class="form-control") }}
        <br/>
        <div class="text-center">
            {{ create_meeting_form.submit(class="btn btn-lg btn-block btn-primary") }}
        </div>
    </form>
</div>
<br/>
<br/>
<br/>
<div class="container">
    <table class="table table-bordered">
        <thead class="text-center">
            <tr>
                <th scope="col">Date</th>
                <th scope="col">Day</th>
                <th scope="col">Hour</th>
                <th scope="col">Pitch</th>
                <th scope="col">Locality</th>
                <th scope="col">Type</th>
                <th scope="col">Actions</th>
            </tr>
        </thead>
        <tbody>
            {% for meeting in meetings %}
            {% include 'includes/meetings_modals.html' %}
                <tr>
                    <td>{{ meeting.date }}</td>
                    <td>{{ meeting.day }}</td>
                    <td>{{ meeting.hour }}</td>
                    <td>{{ meeting.pitch.title().replace("_"," ") }}</td>
                    <td>{{ meeting.locality }}</td>
                    <td>{{ meeting.type.title() }}</td>
                    {% if current_user.user_type == 'player' %}
                    <td>
                        <button class="btn btn-primary"
                                data-bs-toggle="modal"
                                data-bs-target="#Modal-ChangeMeeting-{{ meeting.meeting_id }}">
                            Change
                        </button>
                        <button class="btn btn-danger"
                                data-bs-toggle="modal"
                                data-bs-target="#Modal-DeleteMeeting-{{ meeting.meeting_id }}">
                            Delete
                        </button>
                    </td>
                    {% endif %}
                </tr>
            {% endfor %}
        </tbody>
    </table>
</div>
{% endblock %}

模态:

<!-- Modal Change Meeting -->
<div class="modal fade" id="Modal-ChangeMeeting-{{ meeting.meeting_id }}" tabindex="-1" aria-labelledby="ModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="ChangeMeetingModalLabel">
                    Change:
                    {{ meeting.type.title() }} ({{ meeting.date }} - {{ meeting.hour }})
                </h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <form method="POST">
                <div class="modal-body">
                    {{ update_form.csrf_token }}
                  
                    {{ update_form.date.label }}
                    {{ update_form.date(class="form-control", value=meeting.date) }}
                    <br/>
                    {{ update_form.hour.label }}
                    {{ update_form.hour(class="form-control", value=meeting.hour) }}
                    <br/>
                    {{ update_form.locality.label }}
                    {{ update_form.locality(class="form-control", value=meeting.locality) }}
                    <br/>
                    {{ update_form.type.label }}
                    {{ update_form.type(class="form-control", value=meeting.type) }}
                    <br/>
                    {{ update_form.pitch.label }}
                    {{ update_form.pitch(class="form-control", value=meeting.pitch) }}
                    <br/>
                </div>
                <div class="modal-footer">
                    <input id="update_meeting" name="update_meeting" type="hidden" value="{{ meeting.meeting_id }}">
                    {{ update_form.submit(class="btn btn-success", value="Save Changes") }}
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                </div>
            </form>
        </div>
    </div>
</div>

<!-- Delete Meeting -->
<div class="modal fade" id="Modal-DeleteMeeting-{{ meeting.meeting_id }}" tabindex="-1" aria-labelledby="ModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="DeleteMeetingModalLabel">Delete Meeting</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <p>Are you sure you want to delete meeting - {{ meeting.date }} ({{ meeting.hour }})?</p>
            </div>
            <div class="modal-footer">
                <div class="text-center">
                    <form method="POST">
                        {{ delete_form.csrf_token }}
                        <input id="delete_meeting" name="delete_meeting" type="hidden" value="{{ meeting.meeting_id }}">
                        {{ delete_form.submit(class="btn btn-danger") }}
                    </form>
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Dismiss</button>
                </div>
            </div>
        </div>
    </div>
</div>

表格:

type_choices = [('training', 'Training'),('match', 'Match')]

pitch_choices = [('training_ground', 'Training Ground'), ('stadium', 'Stadium')]
  

      class CreateMeetingForm(FlaskForm):
            date = DateField('Date', validators=[DataRequired()])
            hour = TimeField('Hour', validators=[DataRequired()])
            type = SelectField('Type', choices=type_choices, validators=[DataRequired()])
            locality = StringField('Locality', validators=[Length(min=2, max=20), DataRequired()])
            pitch = SelectField('Pitch', choices=pitch_choices, validators=[DataRequired()])
            submit = SubmitField('Create meeting!')
          
        class UpdateMeetingForm(FlaskForm):
            date = DateField('Date')
            hour = TimeField('Hour')
            type = SelectField('Type', choices=type_choices)
            locality = StringField('Locality', validators=[Length(min=2, max=20)])
            pitch = SelectField('Pitch', choices=pitch_choices)
            submit = SubmitField('Update meeting!')

这是一个解决方案:

from flask import Flask, url_for, render_template_string
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField


app = Flask(__name__)
app.config['SECRET_KEY'] = 'some_rndm_key'


class NameForm(FlaskForm):
    name = StringField('Name')
    submit = SubmitField('Submit Form')


class PhoneForm(FlaskForm):
    phone = StringField('Phone')
    submit = SubmitField('Submit Form')


@app.route('/')
@app.route('/<form>', methods=['GET', 'POST'])
def home(form=None):
    name_form = NameForm()
    phone_form = PhoneForm()
    if form == 'name_form' and name_form.validate_on_submit():
        return 'Submitted name form'
    elif form == 'phone_form' and phone_form.validate_on_submit():
        return 'Submitted phone form'
    return render_template_string('<form method="POST" action="{{ url_for("home", form="name_form") }}">'
                                  '{{ name_form.hidden_tag() }}'
                                  '{{ name_form.name.label }}'
                                  '{{ name_form.name }}'
                                  '{{ name_form.submit }}'
                                  '</form>'
                                  '<br>'
                                  '<form method="POST" action="{{ url_for("home", form="phone_form") }}">'
                                  '{{ phone_form.hidden_tag() }}'
                                  '{{ phone_form.phone.label }}'
                                  '{{ phone_form.phone }}'
                                  '{{ phone_form.submit }}'
                                  '</form>', phone_form=phone_form, name_form=name_form)


app.run(debug=True)

基本上有一个带有变量的路由,在 <form> 标记中,您将操作指定为相同的路由,但添加到变量然后检查变量是什么,非常简单