【问题标题】:Python Flask MySQL commit will insert, will not updatePython Flask MySQL 提交将插入,不会更新
【发布时间】:2020-01-09 15:31:13
【问题描述】:

我可以插入,但我不能更新。代码摘录:

app/models.py

class Location(db.Model):
    __tablename__ = "my_locations"
    loc_id = db.Column(db.Integer, primary_key=True)
    loc_name = db.Column(db.String(50), nullable=False)
    loc_detail = db.Column(db.String(50), nullable=True)
    loc_postal_code = db.Column(db.String(10), nullable=False)
    __table_args__ = (db.UniqueConstraint('loc_name', 'loc_detail', name='_location_name_detail_uc'),
            )

app/forms.py

class LocationForm(FlaskForm):
    loc_id = IntegerField('Loc ID')
    loc_name = StringField('Name' , validators=[DataRequired(), Length(min=6, max=50)])
    loc_detail = StringField('Detail', validators=[Length(max=50), Optional()])
    loc_postal_code = StringField('Postal Code', validators=[DataRequired(), Length(min=4, max=10)])
    submit = SubmitField('Submit')

app/routes.py

@app.route('/edit_location/<string:loc_id>', methods=["GET", "POST"])
@login_required
def edit_location(loc_id):
    if not current_user.is_authenticated:
        return redirect(url_for('index'))

    if loc_id == "0":
        # Empty form
        title_sub = "Add"
        form = LocationForm(loc_id=loc_id)
        # form.loc_id = loc_id
    else:
        # Populated form
        title_sub = "Edit"
        location = Location.query.filter_by(loc_id=loc_id).first()

        form = LocationForm(loc_id=location.loc_id, \
                            loc_name=location.loc_name, \
                            loc_detail=location.loc_detail, \
                            loc_postal_code=location.loc_postal_code
                           )

    if request.method == "POST" and form.validate_on_submit():
        try:
            location = Location(loc_id=form.loc_id.data, \
                                loc_name=form.loc_name.data, \
                                loc_detail=form.loc_detail.data, \
                                loc_postal_code=form.loc_postal_code.data
                               )

            logging.info("edit_location(): location:" + str(location.loc_postal_code))
            if location.loc_detail:
                loc_str = location.loc_name + ', ' + location.loc_detail
            else:
                loc_str = location.loc_name

            if loc_id == "0":
                db.session.add(location)
                db.session.commit()
                flash('Location (' + loc_str + ') added.', 'success')
            else:
                db.session.commit()
                flash('Location (' + loc_str + ') updated.', 'success')

            return redirect(url_for('location'))

        except IntegrityError:
            logging.error("edit_location(): Intg Exception occurred", exc_info=True)
            db.session.rollback()
            flash('Location (' + loc_str + ') already exists.', 'error')

        except DatabaseError:
            logging.error("edit_location(): DB Exception occurred", exc_info=True)
            db.session.rollback()
        except Exception as e:
            flash('Error in form, site administrators have been notified. We apologize for the inconvenience.', 'error')
            logging.error("edit_location(): Exception occurred", exc_info=True)

    return render_template('edit_location.html', title=title_sub + " Location", loc_id=loc_id, form=form)

app/templates/edit_location.html

{% extends "main_page.html" %}

{% block content %}
<div class="edit-location">
  <div class="page-header">
      <h2>{% block title %}{{title}}{% endblock %}</h2>
  </div>

  {% from "_formhelpers.html" import render_field %}
  <form method=post name="editLocationForm" action="{{ url_for('edit_location', loc_id=form.loc_id.data) }}">
        {{ form.csrf_token }}
        <input type="hidden" name="loc_id" value="{{ form.loc_id.data }}">
    <table>
        <tr>{{ render_field(form.loc_name) }} </tr>
        <tr>{{ render_field(form.loc_detail) }}</tr>
        <tr>{{ render_field(form.loc_postal_code) }}</tr>
        <tr>
            <td></td>
            <td><small id="locDetail" class="form-text text-muted">e.g.: Rink A, Field #2, West Court</small></td>
              </tr>
        <tr>
            <td></td>
            <td>
        <a href="#" class="btn btn-primary" onClick="document.editLocationForm.submit();" role="button"> <span>&check;</span> Submit</a>
        <a class="btn btn-primary" href="{{ url_for('location') }}" role="button"> <span>&times;</span> Cancel</a>
            </td>
        </tr>
    </table>
    <p>

    </form>
</div>
{% endblock %}

当我使用edit_locations 插入时,我的loc_id = 0,并且MySQL 提交按预期工作。 当我更新时,我会关注/edit_locations/5/edit_locations/293 之类的链接。表单按预期预填充,我更新了 loc_postal_code,但是当我单击 Submit 时,它不会更新后端的记录。 我可以在日志中看到新的loc_postal_code,所以我知道新值存在。

【问题讨论】:

    标签: python flask flask-sqlalchemy mysql-python flask-wtforms


    【解决方案1】:

    如果你按照我发送的示例代码块编辑你的代码,你想要的问题就会得到解决。

    form = LocationForm(request.form)
    if request.method == "POST" and form.validate_on_submit():
        try:
            if loc_id == "0":
                # Add
                location = Location(loc_id=form.loc_id.data,
                                    loc_name=form.loc_name.data,
                                    loc_detail=form.loc_detail.data,
                                    loc_postal_code=form.loc_postal_code.data)
    
            else:
                # Update
                location = Location.query.filter(Location.loc_id == loc_id).first()
    
                location.loc_name = form.loc_name.data
                location.loc_detail = form.loc_detail.data
                location.loc_postal_code = form.loc_postal_code.data
    
            db.session.add(location)
            db.session.commit()
        except Exception as e:
            # Exceptions
            logging.error("...")
    

    【讨论】:

    • 谢谢,但我想我应该提到我已经尝试过了,在这种情况下,由于重复条目,我得到了一个 IntegrityError:sqlalchemy.exc.IntegrityError: (mysql.connector.errors.IntegrityError) 1062 (23000): Duplicate entry '5' for key 'PRIMARY'
    • 对不起,我错过了这一点,您需要在提交之前更新您想要的列。 location.loc_name = form.loc_name.data ...
    • 我认为这就是我在 if method=POST 之后正在做的事情,然后尝试:“location = Location(loc_id=form.loc_id.data, \”... 等等。
    • 您所做的会插入新行。要更新,您必须执行以下操作:location = Location.query.filter_by(loc_id=loc_id).first() location.loc_name=form.loc_name.data location.loc_detail=form.loc_detail.data location.loc_postal_code=form.loc_postal_code.data db.session.add(location) db.session.commit()
    【解决方案2】:

    谢谢@user11527247!

    这是我最终在 routes.py 中所做的:

    @app.route('/edit_location/<int:loc_id>', methods=["GET", "POST"])
    @login_required
    def edit_location(loc_id):
        if not current_user.is_authenticated:
            return redirect(url_for('index'))
    
        if request.method == "GET":
            if loc_id == 0:
                # Empty form
                title_sub = "Add"
                form = LocationForm(request.form)
                form.loc_id = loc_id
            else:
                # Populated form
                title_sub = "Edit"
                location = Location.query.filter_by(loc_id=loc_id).first()
                form = LocationForm(loc_id=location.loc_id, \
                                loc_name=location.loc_name, \
                                loc_detail=location.loc_detail, \
                                loc_postal_code=location.loc_postal_code
                               )
        else:
            form = LocationForm(request.form)
    
        if request.method == "POST" and form.validate_on_submit():
            try:
                if loc_id == 0:
                    location = Location(loc_id=form.loc_id.data, \
                                    loc_name=form.loc_name.data, \
                                    loc_detail=form.loc_detail.data, \
                                    loc_postal_code=form.loc_postal_code.data
                                   )
                else:
                    location = Location.query.filter_by(loc_id=loc_id).first()
    
                    location.loc_id = form.loc_id.data
                    location.loc_name = form.loc_name.data
                    location.loc_detail = form.loc_detail.data
                    location.loc_postal_code = form.loc_postal_code.data
    
                    if location.loc_detail:
                        loc_str = location.loc_name + ', ' + location.loc_detail
                    else:
                        loc_str = location.loc_name
    
                db.session.add(location)
                db.session.commit()
    
                return redirect(url_for('location'))
    
            except IntegrityError:
                logging.error("edit_location(): Intg Exception occurred", exc_info=True)
                db.session.rollback()
                flash('Location (' + loc_str + ') already exists.', 'error')
    
            except DatabaseError:
                logging.error("edit_location(): DB Exception occurred", exc_info=True)
                db.session.rollback()
            except Exception as e:
                flash('Error in form, site administrators have been notified. We apologize for the inconvenience.', 'error')
                logging.error("edit_location(): Exception occurred", exc_info=True)
    
        return render_template('edit_location.html', title=title_sub + " Location", loc_id=loc_id, form=form)
    
    1. 将参数从string:loc_id更改为int:loc_id,并更新了相关的if语句
    2. 添加了明确的 if request.method == "GET" 以确保您的建议 form = LocationForm(request.form) 在已填充表单的 POST 调用期间没有运行
    3. 在 POST 中根据 loc_id == 0 从位置或表单设置位置值
    4. 最后,包括db.session.add()db.session.commit()

    再次感谢!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-06
      • 1970-01-01
      • 2017-08-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-22
      • 2013-08-01
      • 2016-03-16
      相关资源
      最近更新 更多