简体   繁体   English

将SQLAlchemy对象与现有记录关联(Python / Pyramid)

[英]Associating an SQLAlchemy object with an existing record (Python/Pyramid)

When attempting to add a Widget to the (SQLite) DB, and associate it with an already existing User as defined below: 尝试将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)

I receive the error 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>)] 我收到错误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>)] 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>)]

I can add the value for user.name directly, but this breaks the relationship. 我可以直接为user.name添加值,但这会破坏关系。 For example, widget.user.name would give an error like 'str' object has no attribute 'repository' 例如, widget.user.name会给出类似'str' object has no attribute 'repository'

The backref attribute will do what you need. backref属性将满足您的需求。 Add a relationship to user class as follows: 向用户类添加关系,如下所示:

class User(Base):
    ...
    widget = sqlalchemy.orm.relationship('Widget', backref='user')

With backref attribute sqlalchemy will add a reference to your Widget class which will point User object: 使用backref属性,sqlalchemy将添加对Widget类的引用,该类将指向User对象:

user = request.dbsession.query(User).filter_by(name=user_name).one()
new_widget = Widget(kind='bar', user=user)

Your Widget class has a user attribute which is of type Text , which is basically a string attribute on the Python side of things and is something like VARCHAR column in the database. 您的Widget类具有一个Text类型的user属性,它基本上是Python方面的字符串属性,类似于数据库中的VARCHAR列。 You can not assign a User object to an attribute which expects to be a string. 您不能将User对象分配给期望为字符串的属性。

It also appears that you're trying to create a foreign key relationship using the users.name column - this is certainly possible but is quite unusual considering you also have a surrogate primary key on your User model. 您似乎也尝试使用users.name列创建外键关系 - 这当然是可能的,但考虑到您的User模型上还有一个代理主键,这是非常不寻常的。

You need to set up a relationship between your two ORM classes: 您需要在两个ORM类之间建立关系

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

then you'll be able to do any of the following: 然后你就可以做以下任何事情:

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

You can also set up things from the other end as @metmirr suggested, but the magic ingredient here is sqlalchemy.orm.relationship , not the backref which you may or may not choose to have. 您也可以从另一端设置事情@metmirr建议,但这里的神奇成分是sqlalchemy.orm.relationship ,而不是backref您可能会或可能不会选择有。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM