Hello everyone!
*TL;DR:*
A mapping (class A) has a relationship(to class B). Lazy load is specified.
I want to
1. manually select and filter data from B (the result lets call B')
2. select everything from A
3. outer join A with B'
Problem: when doing
all_b = session.query(B).filter(B.value == 1).subquery()
all_a = session.query(A).join(all_b).all()
it performs correct SQL request, although, when accessing all_a.b performs
an extra SQL request and selects all B (not B'). How do i make select with
the joined data from my subquery instead of selecting whole data from the
database?
*Long with working code:*
I do some kind of scanner management. Each IP can have several open ports.
import datetime
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import NullPool
from sqlalchemy.orm import aliased, joinedload
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String, ForeignKey, Table, Integer, DateTime
Base = declarative_base()
association_table = Table(
'_association', Base.metadata,
Column('ip_id', Integer, ForeignKey('_ips.ip_id')),
Column('host_id', Integer, ForeignKey('_hosts.host_id'))
)
class Sessions(object):
def __init__(self):
self.engine = create_engine('postgresql://127.0.0.1/black',
poolclass=NullPool, echo=True)
self.session_builder = sessionmaker(bind=self.engine,
expire_on_commit=False)
def get_new_session(self):
session = self.session_builder()
return session
def destroy_session(self, session):
session.close()
class IPDatabase(Base):
__tablename__ = '_ips'
ip_id = Column(Integer, primary_key=True, autoincrement=True)
# The hostnames that point to this IP
hostnames = relationship(
"HostDatabase",
secondary=association_table,
back_populates="ip_addresses",
lazy='select'
)
# Open ports
ports = relationship('PortDatabase', cascade="all, delete-orphan",
lazy='select')
date_added = Column(DateTime, default=datetime.datetime.utcnow)
def __repr__(self):
return """ IP=(id={}, ports={}) """.format(self.ip_id, self.ports)
class PortDatabase(Base):
__tablename__ = '_ports'
ports_id = Column(Integer, primary_key=True, autoincrement=True)
data = Column(String)
port_number = Column(Integer)
date_added = Column(DateTime, default=datetime.datetime.utcnow)
# The name of the related project
target = Column(
Integer, ForeignKey('_ips.ip_id', ondelete='CASCADE')
)
def __repr__(self):
return """ Port=(id={}, port={}) """.format(self.ports_id,
self.port_number)
def create():
sessions = Sessions()
Base.metadata.drop_all(sessions.engine)
Base.metadata.create_all(sessions.engine, checkfirst=True)
session_spawner = Sessions()
session = session_spawner.get_new_session()
ip_1 = IPDatabase()
ip_2 = IPDatabase()
ip_3 = IPDatabase()
port_1 = PortDatabase(port_number=80)
port_2 = PortDatabase(port_number=80)
port_3 = PortDatabase(port_number=443)
ip_1.ports.append(port_1)
ip_1.ports.append(port_2)
ip_1.ports.append(port_3)
session.add(ip_1)
session.add(ip_2)
session.add(ip_3)
session.add(port_1)
session.add(port_2)
session.add(port_3)
session.commit()
session_spawner.destroy_session(session)
def main():
session_spawner = Sessions()
session = session_spawner.get_new_session()
subq = session.query(PortDatabase).filter(PortDatabase.port_number ==
80).subquery()
ips = session.query(IPDatabase).join(subq).all()
session_spawner.destroy_session(session)
print(ips) # This will fail, as 'ports' were not loaded due to
lazyload='select'
if __name__ == '__main__':
main()
Any help would be really great, as i have read tons of manuals and other
resources, but still cannot find the solution.
Thanks,
Anatoly
--
SQLAlchemy -
The Python SQL Toolkit and Object Relational Mapper
http://www.sqlalchemy.org/
To post example code, please provide an MCVE: Minimal, Complete, and Verifiable
Example. See http://stackoverflow.com/help/mcve for a full description.
---
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.