【问题标题】:Defining ORM relationships in sqlalchemy在 sqlalchemy 中定义 ORM 关系
【发布时间】:2015-04-29 13:05:40
【问题描述】:

我正在深入研究 sqlalchemy ORM,并试图了解对象之间的关系。

我创建了 3 个类,分别代表日志文件 (Log)、从日志文件解析的记录 (LogRecord) 和每个日志记录所属的用户 (User)。

我是这样定义类的:

from sqlalchemy import Table, Column, Integer, String, ForeignKey, create_engine
from sqlalchemy.orm import relationship, backref, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
import random

engine = create_engine('sqlite://')
# Create the session class
Session = sessionmaker(bind=engine)
# Create the session
session = Session()

Base = declarative_base()

class Log(Base):

    __tablename__ = 'logs'

    id = Column(Integer, primary_key=True, unique=True)
    log_name = Column(String, unique=True)
    records = relationship("LogRecord", backref="logs")

    def __repr__(self):
        return '<Log(log_name={:s}, id={:d}>'.format(
            self.log_name, self.id)

class LogRecord(Base):

    __tablename__ = 'log_records'

    id = Column(Integer, primary_key=True, unique=True)
    record_name = Column(String)
    log_id = Column(Integer, ForeignKey('logs.id'))
    user_id = Column(Integer, ForeignKey('user.id'))

    user = relationship("User", backref="log_records")

    def __repr__(self):
        return '<LogRecord(record_name={:s}, id={:d}>'.format(
            self.record_name,
            self.id)

class User(Base):

    __tablename__ = 'user'

    id = Column(Integer, primary_key=True, unique=True)
    name = Column(String, unique=True)

    def __repr__(self):
        return '<User(name={:s}, id={:d}>'.format(self.name, self.id)

然后用一些虚假数据填充它们:

Base.metadata.create_all(engine)

users = ['John', 'Alex', 'Nikki']

# Add 10 log files to Log
for x in range(0,10):
    log = Log(log_name='log{:d}.txt'.format(x))
    session.add(log)

# Add users
for user in users:
    session.add(User(name=user))

# Select all users
users = session.query(User).all()

# Add log records
for log in session.query(Log):
    # Assign a random user to each log record
    user = users[int(random.random() * len(users))]
    for x in range(0,10):
        # Assign a random user to each log record
        user = users[int(random.random() * len(users))]
        r = LogRecord(record_name='{:s}-{:d}'.format(log.log_name, int(random.random()*100)),log_id=log.id,user=user)

        session.add(r)

每个日志文件都可以包含来自一个或多个用户的记录。我想获得一份不同的日志文件列表,其中至少包含来自指定用户的一条记录。我试过了:

In [8]: user = session.query(User).filter(User.name == 'John').one()

In [9]: user
Out[9]: <User(name=John, id=1>

然后尝试使用以下命令查找日志:

In [10]: session.query(Log).filter(Log.records.user == user).all()

但是得到了以下信息:

session.query(Log).filter(Log.records.user == user).distinct().all()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-13-d6d323e178f8> in <module>()
----> 1 session.query(Log).filter(Log.records.user == user).distinct().all()

/Users/kerfoot/code/venvs/sqlalchemy/lib/python2.7/sitepackages/sqlalchemy/orm/attributes.pyc in __getattr__(self, key)
192                     type(self.comparator).__name__,
193                     self,
--> 194                     key)
195             )
196 

AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with Log.records has an attribute 'user'

不确定我的类定义或查询本身是否有问题。

非常感谢任何帮助!

【问题讨论】:

    标签: python-2.7 sqlalchemy


    【解决方案1】:

    您不能对属性的属性进行过滤,或者简单地说:表达式中不能有多个点:Log.records.user 不起作用。

    Option-1:您可以像在 SQL 中那样做:

    session.query(Log).join(LogRecord, Log.records).filter(LogRecord.user == user).all()
    

    sqlalchemy 足够聪明,可以只返回Log 实例的列表而没有任何重复(即使SQL 语句可能会导致重复)。

    Option-2:另一种方法是使用any(...),这逻辑上更简洁:

    session.query(Log).filter(Log.records.any(LogRecord.user == user)).all()
    

    成绩单:
    -> 获取所有Log 实例,
    -> 其中至少包含一个LogRecord,
    -> 属于给定的user

    【讨论】:

      猜你喜欢
      • 2018-10-04
      • 2021-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-17
      • 1970-01-01
      • 2020-05-16
      • 2021-06-26
      相关资源
      最近更新 更多