我正在尝试在此关联表中插入角色数据:
class Association(db.Model):
__tablename__ = 'associations'
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True)
team_id = db.Column(db.Integer, db.ForeignKey('teams.id'), primary_key=True)
role = db.Column(db.String)
user = db.relationship("User", back_populates="teams")
team = db.relationship("Team", back_populates="users")
它链接到另外 2 个表:
class User(db.Model, UserMixin):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String)
username = db.Column(db.String, nullable=False, unique=True, index=True)
password_hash = db.Column(db.String)
teams = db.relationship("Association", back_populates="user")
class Team(db.Model):
__tablename__ = 'teams'
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String)
player = db.Column(db.String)
users = db.relationship("Association", back_populates="team")
但是,当我尝试在关联表中插入角色时:
t = Team.query.filter_by(id=team_name1_id).first()
a = Association(role=form.role.data)
a.user = User.query.filter_by(id=current_user.id).first()
t.users.append(a)
db.session.add(t)
db.session.commit()
我收到这个错误:
IntegrityError: (raised as a result of Query-invoked autoflush; consider using a session.no_autoflush block if this flush is occurring prematurely) (sqlite3.IntegrityError) NOT NULL constraint failed: association.team_id [SQL: u'INSERT INTO association (user_id, role) VALUES (?, ?)'] [parameters: (1, u'point guard')]
你知道我该如何解决吗?
最佳答案
导致 autoflush 的行是
t.users.append(a)
你还没有定义你的 relationship loading strategies , 所以它们默认为 "select"
.由于您是第一次访问 Team.users
关系属性,它将发出一个 SELECT 以获取相关对象。
您还间接地对 session 进行了更改
a.user = User.query.filter_by(id=current_user.id).first()
由于save-update cascade , 默认情况下,将新的 Association
实例也放置到 session 中。
为了保持数据库和 session 的状态一致,SQLAlchemy 必须 flush您在发出查询之前对 DB 所做的更改,因此半初始化的 Association
在与 Team
实例关联之前被发送到 DB。
可能的解决方案:
Temporarily disable the autoflush feature对于那个特定的追加,因为你知道你正在添加一个新的
Association
:with db.session.no_autoflush: t.users.append(a)
不过,SELECT 仍会发出。
逆向操作。不是将
Association
实例附加到Team.users
集合,而是将Team
分配给Association.team
:# Instead of t.users.append(a): a.team = t # Mr.
一个不太明显的解决方案是 eager load获取
Team
实例时关系的内容,因此不需要 SELECT:t = db.session.query(Team).options(db.joinedload(Team.users)).first()
或者使用
db.noload(Team.users)
根本不加载它们选项。
注意
db.session.add(t)
是多余的。获取的 Team
实例已经在 session 中——否则 Team.users
的延迟加载 could not have proceeded首先。
关于python - 使用 SQLAlchemy 在关联表中插入数据时出现 IntegrityError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48188660/