来自join的SQLAlchemy声明属性(单个属性,不是整个对象)

Cor*_*hin 8 python orm sqlalchemy declarative

我希望创建一个从另一个表填充的对象的映射属性.

使用SQLAlchemy文档示例,我希望在Address类中存在一个user_name字段,以便可以轻松查询和轻松访问它(无需第二次往返数据库)

例如,我希望能够查询和过滤user_name Address.query.filter(Address.user_name == 'wcdolphin').first() 并且还可以访问user_name所有Address对象的属性,而不会降低性能,并使其正确保持写入,就像预期的属性一样.__tablename__

class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    addresses = relation("Address", backref="user")

class Address(Base):
    __tablename__ = 'addresses'

    id = Column(Integer, primary_key=True)
    email = Column(String(50))
    user_name = Column(Integer, ForeignKey('users.name'))#This line is wrong
Run Code Online (Sandbox Code Playgroud)

我该怎么做呢?

我发现文档相对难以理解,因为它似乎不符合大多数示例,尤其是Flask-SQLAlchemy示例.

sch*_*mar 6

您可以使用join查询对象上的a执行此操作,无需直接指定此属性.所以你的模型看起来像:

from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.orm import sessionmaker, relation
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
engine = create_engine('sqlite:///')
Session = sessionmaker(bind=engine)

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    addresses = relation("Address", backref="user")

class Address(Base):
    __tablename__ = 'addresses'
    id = Column(Integer, primary_key=True)
    email = Column(String(50))
    user_id = Column(Integer, ForeignKey("users.id"))


Base.metadata.create_all(engine)
Run Code Online (Sandbox Code Playgroud)

过滤用户名的地址后的查询如下所示:

>>> session = Session()
>>> session.add(Address(user=User(name='test')))
>>> session.query(Address).join(User).filter(User.name == 'test').first()
<__main__.Address object at 0x02DB3730>
Run Code Online (Sandbox Code Playgroud)

编辑:由于您可以从地址对象直接访问用户,因此无需直接将属性引用到Address类:

>>> a = session.query(Address).join(User).filter(User.name == 'test').first()
>>> a.user.name
'test'
Run Code Online (Sandbox Code Playgroud)