如何阻止SqlAlchemy生成插入或更新主键的SQL ?



我有一个模型:

class Contact(db.Model):
__tablename__ = 'contact'
contactid = db.Column(db.BigInteger, primary_key=True, server_default=db.text("nextval('contact_contactid_seq'::regclass)"))
firstname = db.Column(db.Text)
lastname = db.Column(db.Text)

和一个表单

class ContactForm(FlaskForm):
contactid = HiddenField('contactid')
firstname = StringField('First Name', validators=[Optional()], filters = [lambda x: x or None])
lastname = StringField('Last Name', validators=[Optional()], filters = [lambda x: x or None])
submit = SubmitField('Save')

我使用类似于下面的代码使用上述模型和表单

在数据库中插入和更新记录
@blueprint.route('/create', methods=['GET', 'POST'])
def create():
form = ContactForm()
if form.validate_on_submit():
r = Contact()
form.populate_obj(r)
db.session.add(r)
db.session.commit()
flash("saved new record", "success")
return root()
return render_template('contact/create.html', form=form)

@blueprint.route('/edit/<id>', methods=['GET', 'POST'])
def edit(id: int):
r = Contact.query.get_or_404(id)
form = ContactForm(obj=r)
if form.validate_on_submit():
form.populate_obj(r)
db.session.commit()
flash("updated record", "success")
return redirect(url_for('blueprint.root'))
return render_template('contact/edit.html', form=form)

SQLAlchemy生成的SQL如下:

INSERT INTO contact (contactid, firstname, lastname) VALUES (%(contactid)s, %(firstname)s, %(lastname)s)
UPDATE contact set contactid=%(contactid)s, firstname=%(firstname)s, lastname=%(lastname)s WHERE contactid = %(contactid)s

我想让它这样做:

INSERT INTO contact (firstname, lastname) VALUES (%(firstname)s, %(lastname)s)
SELECT last_contactid_somehow
UPDATE contact set firstname=%(firstname)s, lastname=%(lastname)s WHERE contactid = %(contactid)s

我做错了什么?

我想要一个解决方案SqlAlchemy:

  • 处理自动递增的主键而不将其插入插入语句
  • 没有在update语句
  • 中设置主键。

我正在使用Postgres

我认为第一个问题将通过设置autoincrement=True来解决

class Contact(db.Model):
__tablename__ = 'contact'
contactid = db.Column(db.BigInteger, primary_key=True, autoincrement=True, server_default=db.text("nextval('contact_contactid_seq'::regclass)"))
...

第二个问题实际上是正常工作的,因为你这样定义了表单类。

此外,您想要的查询和SQLAlchemy生成的查询是相同的,因为where子句中的契约和set子句中的契约是相同的。

但是,如果您想更改查询,请更改模型对象的值。

r = Contact.query.get_or_404(id)
form = ContactForm(obj=r)
if form.validate_on_submit():
r.firstname = form.firstname.data
r.lastname = form.lastname.data
db.session.commit()
...

最新更新