#python #sqlalchemy
#python #sqlalchemy
Вопрос:
У меня есть две таблицы Items и ItemDescriptions
class Item(Base):
__tablename__ = "item"
id = Column(Integer, primary_key=True)
description_id = Column(Integer, ForeignKey('item_description.id'))
class ItemDescription(Base):
__tablename__ = "item_description"
id = Column(Integer, primary_key=True)
Учитывая список ItemDescriptions, я хочу получить список элементов таким образом, чтобы в каждом идентификаторе ItemDescription было по одному элементу. Мне все равно, какой элемент.
[Отредактировано для наглядности]
Учитывая этот список элементов и описаний:
Item, Description
1 , 1
2 , 1
3 , 1
4 , 2
5 , 2
6 , 3
7 , 3
8 , 3
Я хочу запрос, который вернет что-то вроде:
Item, Description
2 , 1
4 , 2
7 , 3
У меня возникли проблемы с обработкой подзапросов и т.д.
Спасибо за вашу помощь
Ответ №1:
Я большой поклонник column_property. Вот способ сделать то, что вы хотите, с помощью column_property:
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Item(Base):
__tablename__ = 'item'
id = Column(Integer, primary_key=True)
description_id = Column(Integer, ForeignKey('item_description.id'))
class ItemDescription(Base):
__tablename__ = 'item_description'
id = Column(Integer, primary_key=True)
any_item_id = column_property(
select(
[Item.id],
id == Item.description_id,
limit=1,
).label('any_item_id'),
deferred=True,
)
e = create_engine('sqlite://', echo=True)
Base.metadata.create_all(e)
s = Session(e)
descriptions = [
ItemDescription(id=1),
ItemDescription(id=2),
ItemDescription(id=3),
]
s.add_all(descriptions)
items = [
Item(id=1, description_id=1),
Item(id=2, description_id=1),
Item(id=3, description_id=1),
Item(id=4, description_id=2),
Item(id=5, description_id=2),
Item(id=6, description_id=3),
Item(id=7, description_id=3),
Item(id=8, description_id=3),
]
s.add_all(items)
query = s.query(ItemDescription).options(undefer('any_item_id'))
for description in query:
print description.any_item_id, description.id
# alternative way without using column_property
query = s.query(
select(
[Item.id],
ItemDescription.id == Item.description_id,
limit=1,
).label('any_item_id'),
ItemDescription,
)
for item_id, description in query:
print item_id, description.id
Комментарии:
1. column_property выглядит великолепно, спасибо! Если бы я хотел сделать это как отдельный запрос, а не свойство столбца, поместил бы я select в подзапрос?
2. Да, вы можете переместить select в запрос. Я добавил это к ответу. Лично я все еще предпочитаю column_property, хотя 🙂
3. Мне нравится метод column_query, но спасибо, что также показали способ запроса in.
Ответ №2:
from sqlalchemy.orm import relationship, backref
class Item(Base):
__tablename__ = "item"
id = Column(Integer, primary_key=True)
description_id = Column(Integer, ForeignKey('item_description.id'))
desc = relationship(User, backref=backref('desc', order_by=id))
class ItemDescription(Base):
__tablename__ = "item_description"
id = Column(Integer, primary_key=True)
Now your every ItemDescription class will have an backref called `desc` which is nothing but a list of Item.
Now you can do something like this
item_desc = session.query(ItemDescription).
... options(joinedload('desc').all()
for item in item_desc:
print item.desc
Я думаю, что это может не дать вам точного ответа. я думаю, это поможет
Комментарии:
1. Извините, мое объяснение не очень понятно, я отредактирую его, чтобы сделать более понятным.