将 SQLAlchemy 对象与现有记录相关联 (Python/Pyramid)
Associating an SQLAlchemy object with an existing record (Python/Pyramid)
当尝试将 Widget
添加到 (SQLite) 数据库,并将其与已存在的 User
相关联时,定义如下:
class Widget(Base):
__tablename__ = 'widgets'
id = Column(Integer, primary_key=True)
kind = Column(Text)
user = Column(Text, ForeignKey('users.name'))
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(Text, unique=True)
@view_config(route_name='name', renderer='json')
def add_widget(request):
user_name = 'foo'
user = request.dbsession.query(User).filter_by(name=user_name).one()
new_widget = Widget(kind='bar', user=user)
我收到错误 sqlalchemy.exc.InterfaceError: (sqlite3.InterfaceError) Error binding parameter 1 - probably unsupported type. [SQL: 'INSERT INTO widgets (kind, user) VALUES (?, ?)'] [parameters: ('bar', <example.models.user.User object at 0x1050bdghd>)]
我可以直接添加 user.name
的值,但这会破坏关系。例如,widget.user.name
会给出类似 'str' object has no attribute 'repository'
的错误
backref
属性将满足您的需要。添加与用户 class 的关系如下:
class User(Base):
...
widget = sqlalchemy.orm.relationship('Widget', backref='user')
使用 backref 属性,sqlalchemy 将添加对您的 Widget class 的引用,它将指向用户对象:
user = request.dbsession.query(User).filter_by(name=user_name).one()
new_widget = Widget(kind='bar', user=user)
你的 Widget
class 有一个 user
类型的 Text
属性,它基本上是 Python 方面的字符串属性类似于数据库中的 VARCHAR 列。您不能将用户对象分配给应为字符串的属性。
您似乎也在尝试使用 users.name
列创建外键关系 - 这当然是可能的,但考虑到您在 [=16= 上也有一个代理主键,这是非常不寻常的] 模特。
您需要在两个 ORM classes 之间设置 relationship:
class Widget(Base):
__tablename__ = 'widgets'
id = Column(Integer, primary_key=True)
kind = Column(Text)
user_id = Column(Integer, ForeignKey('users.id'))
user = sqlalchemy.orm.relationship('User', backref='widgets')
然后您就可以执行以下任一操作:
new_widget = Widget(kind='bar', user=user)
new_widget = Widget(kind='bar', user_id=user.id)
user.widgets.append(Widget(kind='bar'))
new_widget.user_id = user.id
new_widget.user = user
您也可以按照@metmirr 的建议从另一端进行设置,但这里的神奇成分是 sqlalchemy.orm.relationship, not the backref,您可以选择也可以不选择。
当尝试将 Widget
添加到 (SQLite) 数据库,并将其与已存在的 User
相关联时,定义如下:
class Widget(Base):
__tablename__ = 'widgets'
id = Column(Integer, primary_key=True)
kind = Column(Text)
user = Column(Text, ForeignKey('users.name'))
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(Text, unique=True)
@view_config(route_name='name', renderer='json')
def add_widget(request):
user_name = 'foo'
user = request.dbsession.query(User).filter_by(name=user_name).one()
new_widget = Widget(kind='bar', user=user)
我收到错误 sqlalchemy.exc.InterfaceError: (sqlite3.InterfaceError) Error binding parameter 1 - probably unsupported type. [SQL: 'INSERT INTO widgets (kind, user) VALUES (?, ?)'] [parameters: ('bar', <example.models.user.User object at 0x1050bdghd>)]
我可以直接添加 user.name
的值,但这会破坏关系。例如,widget.user.name
会给出类似 'str' object has no attribute 'repository'
backref
属性将满足您的需要。添加与用户 class 的关系如下:
class User(Base):
...
widget = sqlalchemy.orm.relationship('Widget', backref='user')
使用 backref 属性,sqlalchemy 将添加对您的 Widget class 的引用,它将指向用户对象:
user = request.dbsession.query(User).filter_by(name=user_name).one()
new_widget = Widget(kind='bar', user=user)
你的 Widget
class 有一个 user
类型的 Text
属性,它基本上是 Python 方面的字符串属性类似于数据库中的 VARCHAR 列。您不能将用户对象分配给应为字符串的属性。
您似乎也在尝试使用 users.name
列创建外键关系 - 这当然是可能的,但考虑到您在 [=16= 上也有一个代理主键,这是非常不寻常的] 模特。
您需要在两个 ORM classes 之间设置 relationship:
class Widget(Base):
__tablename__ = 'widgets'
id = Column(Integer, primary_key=True)
kind = Column(Text)
user_id = Column(Integer, ForeignKey('users.id'))
user = sqlalchemy.orm.relationship('User', backref='widgets')
然后您就可以执行以下任一操作:
new_widget = Widget(kind='bar', user=user)
new_widget = Widget(kind='bar', user_id=user.id)
user.widgets.append(Widget(kind='bar'))
new_widget.user_id = user.id
new_widget.user = user
您也可以按照@metmirr 的建议从另一端进行设置,但这里的神奇成分是 sqlalchemy.orm.relationship, not the backref,您可以选择也可以不选择。