gpt4 book ai didi

python - 如何仅加载指定的列并仍然获得模型对象? (不延期)

转载 作者:太空宇宙 更新时间:2023-11-03 18:12:51 25 4
gpt4 key购买 nike

我想要:

  1. 从多个表/模型中仅加载我想要的字段。
  2. 取回“模型对象”,而不是我将列传递给 session.query 的类似命名元组的对象。这应该跨越关系,例如 employee.company.name,其中 company 是 Employee 模型中的关系字段。
  3. 防止在初始选择查询后无意中加载其他字段。我可以使用 defer.load_only('field_name') 但其他人可以访问我未指定的模型的属性,这将导致另一个查询运行。理想情况下,访问查询中未指定的字段会引发 AttributeError,即使该字段已在模型中定义。

使用 SqlAlchemy 提供的机制可以实现这一点吗?这会是一个好主意吗?

我编写了以下函数来实现我想要的功能,但似乎其他人一定已经以更好、更标准的方式满足了这些需求。

class Attributable(object):
pass


def spread_result(row, columns):
"""
:type row: sqlalchemy.util._collections.KeyedTuple
:type columns: tuple
Usage:
>>> result = session.query(Model.field, AnotherModel.other_field).first()
>>> obj = spread_result(result, ('field', 'another_model.other_field'))
>>> obj.field
'field_value'
>>> obj.another_model.other_field
'other_field_value'
>>> obj.another_mapped_field
AttributeError: 'Attributable' object has no attribute 'another_mapped_field'
"""
root = Attributable()
for column, value in zip(columns, row):
obj = root
parts = column.split('.')
for i, attr in enumerate(parts):
if i == len(parts) - 1:
setattr(obj, attr, value)
else:
setattr(obj, attr, Attributable())
obj = getattr(obj, attr)

return root

最佳答案

最简单的方法是创建一个“公共(public)”模型,该模型映射到同一个表,但仅包含您希望可加载/可访问的列和其他属性。

relevant documentation说:

the include_properties or exclude_properties arguments can specify that only a subset of columns should be mapped

如果您有一个 Person 模型,用户应该只从中看到 id 和 name,那么“public”类将如下所示:

class PublicPerson(Base):
__table__ = Person.__table__

__mapper_args__ = {
'include_properties': ['id', 'name']
}

这是一个简单的可运行示例:

from datetime import datetime
from sqlalchemy import create_engine, Column, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session

engine = create_engine('sqlite://', echo=True)
session = Session(bind=engine)
Base = declarative_base(bind=engine)


class Person(Base):
__tablename__ = 'person'

id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
birthday = Column(DateTime, nullable=False)


class PublicPerson(Base):
__table__ = Person.__table__

__mapper_args__ = {
'include_properties': ['id', 'name']
}


Base.metadata.create_all()

session.add(Person(name='Jan', birthday=datetime(2001, 1, 1)))

# query the full person, prints birthday
print(session.query(Person.birthday).scalar())

# query the "public" person, raises exception on birthday
print(session.query(PublicPerson.birthday).scalar())

关于python - 如何仅加载指定的列并仍然获得模型对象? (不延期),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25554508/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com