我正在尝试在此关联表中插入角色数据:
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")
Run Code Online (Sandbox Code Playgroud)
它链接到另外两个表:
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")
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试在关联表中插入角色时:
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()
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
IntegrityError :(由于查询调用的自动刷新而引发;如果此刷新过早发生,请考虑使用session.no_autoflush块)(sqlite3.IntegrityError)NOT NULL约束失败:association.team_id [SQL:u'INSERT INTO关联(user_id ,角色)VALUES(?,?)'] [参数:(1,u'控球后卫')]
你知道我该怎么解决吗?
导致自动刷新的行是
t.users.append(a)
Run Code Online (Sandbox Code Playgroud)
您尚未定义关系加载策略,因此默认为"select"。由于您是Team.users第一次访问Relationship属性,因此它将发出SELECT以便获取相关对象。
您还通过以下方式间接更改了会话
a.user = User.query.filter_by(id=current_user.id).first()
Run Code Online (Sandbox Code Playgroud)
由于默认情况下为save-update Cascade,它也将新Association实例也放置到会话中。
为了保持数据库和会话状态的一致性,SQLAlchemy必须在发出查询之前将您的更改刷新到数据库,因此初始化的一半将Association在与Team实例关联之前发送到数据库。
可能的解决方案:
暂时禁用该特定追加的自动刷新功能,因为您知道要添加新的Association:
with db.session.no_autoflush:
t.users.append(a)
Run Code Online (Sandbox Code Playgroud)
SELECT仍然会发出。
反转操作。无需将Association实例附加到Team.users集合,而是将分配Team给Association.team:
# Instead of t.users.append(a):
a.team = t # Mr.
Run Code Online (Sandbox Code Playgroud)一个不太明显的解决方案是在获取实例时急于加载关系的内容Team,因此不需要SELECT:
t = db.session.query(Team).options(db.joinedload(Team.users)).first()
Run Code Online (Sandbox Code Playgroud)
或根本不使用该db.noload(Team.users)选项加载它们。
注意
db.session.add(t)
Run Code Online (Sandbox Code Playgroud)
是多余的。提取的Team实例已经在会话中–否则,首先Team.users 不能进行的懒惰加载。
| 归档时间: |
|
| 查看次数: |
855 次 |
| 最近记录: |