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

发布于 2025-02-04 18:36:01 字数 2104 浏览 4 评论 0原文

我有一个模型:

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)

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:

  • 处理自动插入的主键而不将其粘贴到插入语句中
  • 不会设置更新语句中的主键,

我正在使用Postgres

I have a model:

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)

and a form

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')

I use code similar to the following to insert and update records in the database using the above model and form

@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)

The Problem

SQLAlchemy appears to be generating SQL like this:

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

I want it to do it like this:

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

What am I doing wrong?

I would like a solution where SqlAlchemy:

  • handles the auto-incrementing primary key without sticking it into the insert statement
  • doesn't set the primary key in the update statement

I am using Postgres

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

大姐,你呐 2025-02-11 18:36:01

就可以解决第一个问题

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)"))
    ...

我认为,将通过设置自动启动= true 第二个问题实际上是正常工作,因为您将表单类定义为这样,

。此外,您想要的查询和sqlalchemy生成的查询是相同的,因为在where子句中的contrentId和集合子句中的contractid中的consctionId相同。

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

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()
        ...

I think the first problem will be solved by setting 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)"))
    ...

the second problem is actually working properly because you defined the form class like that.

In addition, the query you want and the query generated by SQLAlchemy are the same because the contractid in the where clause and the contractid in the set clause is same.

Nevertheless, if you want to change the query, change the value of the model object.

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()
        ...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文