【问题标题】:Associating an SQLAlchemy object with an existing record (Python/Pyramid)将 SQLAlchemy 对象与现有记录关联(Python/Pyramid)
【发布时间】:2017-07-07 14:46:38
【问题描述】:

当尝试将 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' 的错误

【问题讨论】:

    标签: python sqlite sqlalchemy pyramid


    【解决方案1】:

    您的Widget 类具有user 类型的Text 属性,它基本上是Python 方面的字符串属性,类似于数据库中的VARCHAR 列。您不能将 User 对象分配给期望为字符串的属性。

    您似乎也在尝试使用 users.name 列创建外键关系 - 这当然是可能的,但考虑到您的 User 模型上还有一个代理主键,这是非常不寻常的。

    您需要在两个 ORM 类之间设置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,而不是您可能会或可能不会选择拥有的backref

    【讨论】:

      【解决方案2】:

      backref 属性将满足您的需求。添加与用户类的关系如下:

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

      使用 backref 属性,sqlalchemy 将添加对您的 Widget 类的引用,该类将指向 User 对象:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多