Python+SQLAlchemy操作PostgreSQL插入数据触发外键约束报错如何解决
错误原因
你的模型本身已经配置了主键自动生成规则:两个表的id字段都定义为Integer类型的主键,SQLAlchemy对接PostgreSQL时会自动为该字段配置自增序列,无需额外调整。
本次报错的核心问题是外键关联逻辑错误:
- 你在创建
Book对象时硬编码了pub_id=1/2,但调用db.session.add_all([p1,p2,p3])之后,三个出版社对象还没有被写入数据库,自增主键id尚未生成,你无法提前预判准确的id值 - 就算你之前清空过表,PostgreSQL的自增序列不会随数据删除重置,新插入的出版社id可能从大于1的数值开始,硬编码的id自然不存在。
解决方案1:flush后获取主键再创建Book
调用db.session.flush()会把临时数据写入数据库、生成主键但不提交事务,后续操作出错可以正常回滚,不会产生脏数据。修改后的run_app.py代码如下:
from run import db, Book, Publication p1 = Publication("Oxford Publications") p2 = Publication("Paramount Press") p3 = Publication("Oracle Books Inc") db.session.add_all([p1,p2,p3]) # 新增flush操作,生成三个出版社的主键id db.session.flush() # 直接用出版社对象的id属性填充外键,不需要硬编码 b1 = Book("Miky's Delivery Service", "William Dobelli", 3.9, "ePub", "broom-145379.svg", 123, p1.id) b2 = Book("The Secret Life of Walter Kitty", "Kitty Stiller", 4.1, "Hardcover", "cat-150306.svg", 133, p1.id) b3 = Book("The Empty Book of Life", "Roy Williamson", 4.2, "eBook", "book-life-34063.svg", 153, p1.id) b4 = Book("Life After Dealth", "Nikita Kimmel", 3.8, "Paperback", "mummy-146868.svg", 175, p2.id) b5 = Book("The Legend of Dracula", "Charles Rowling", 4.6, "Hardcover", "man-37603.svg", 253, p2.id) b6 = Book("Taming Dragons", "James Vonnegut", 4.5, "MassMarket Paperback", "dragon-23164.svg", 229, p2.id) db.session.add_all([b1,b2,b3,b4,b5,b6]) db.session.commit()
解决方案2:使用ORM关系映射自动关联(更推荐)
在模型中定义双向关系后,不需要手动维护外键赋值,直接关联对象即可,SQLAlchemy会自动处理外键填充、写入顺序。
首先修改run.py中的Publication模型,新增关系字段:
class Publication(db.Model): __tablename__ = 'publication' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80), nullable=False) # 新增双向关系字段,backref会自动在Book类中生成publication属性 books = db.relationship('Book', backref='publication', lazy=True) # 原有__init__、__repr__代码保持不变
修改后的run_app.py写法如下,不需要硬编码外键,也不需要提前flush:
from run import db, Book, Publication p1 = Publication("Oxford Publications") p2 = Publication("Paramount Press") p3 = Publication("Oracle Books Inc") # 创建图书对象时pub_id传空值,后续通过关系绑定 b1 = Book("Miky's Delivery Service", "William Dobelli", 3.9, "ePub", "broom-145379.svg", 123, None) b2 = Book("The Secret Life of Walter Kitty", "Kitty Stiller", 4.1, "Hardcover", "cat-150306.svg", 133, None) b3 = Book("The Empty Book of Life", "Roy Williamson", 4.2, "eBook", "book-life-34063.svg", 153, None) # 绑定图书到对应出版社 p1.books.extend([b1,b2,b3]) b4 = Book("Life After Dealth", "Nikita Kimmel", 3.8, "Paperback", "mummy-146868.svg", 175, None) b5 = Book("The Legend of Dracula", "Charles Rowling", 4.6, "Hardcover", "man-37603.svg", 253, None) b6 = Book("Taming Dragons", "James Vonnegut", 4.5, "MassMarket Paperback", "dragon-23164.svg", 229, None) p2.books.extend([b4,b5,b6]) # 一次性提交所有对象即可,SQLAlchemy会自动处理写入顺序和外键赋值 db.session.add_all([p1,p2,p3,b1,b2,b3,b4,b5,b6]) db.session.commit()
内容的提问来源于stack exchange,提问作者minTwin
相关产品推荐
相关产品推荐

