Load subset of joined columns in SQLAlchemy - python

I'm trying to load a subset of columns from multiple joined tables in SQLAlchemy and can't figure out the magic syntax.
Here's a simple example of what I'm trying to do. It results in an error (below):
from sqlalchemy import create_engine
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, load_only
Base = declarative_base()
class Table1(Base):
__tablename__ = 'table1'
table1_id = Column(Integer, primary_key=True)
table1_val = Column(String)
r1 = relationship('Table2', backref = 'r2')
class Table2(Base):
__tablename__ = 'table2'
table2_id = Column(Integer, ForeignKey('table1.table1_id'), primary_key=True)
table2_val = Column(String)
from sqlalchemy.orm import sessionmaker
some_engine = create_engine('postgresql://scott:tiger#localhost/')
Session = sessionmaker(bind=some_engine)
session = Session()
query = session.query(Table1).join(Table2).options(load_only('table1_val','table2_val'))
ArgumentError: Can't find property named 'table2_val' on the mapped entity Mapper|Table1|table1 in this Query.
How do I pick and choose columns from these multiple tables?

Question was answered at [https://bitbucket.org/zzzeek/sqlalchemy/issues/3679/multiple-load_only-in-queryoptions-ignore]
Here is the corrected code:
from sqlalchemy import create_engine
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import joinedload, Load, relationship, load_only
Base = declarative_base()
class Table1(Base):
__tablename__ = 'table1'
global_id = Column(Integer, primary_key=True)
table1_val1 = Column(String)
table1_val2 = Column(String)
r1 = relationship('Table2', backref = 'r2')
class Table2(Base):
__tablename__ = 'table2'
global_id = Column(Integer, ForeignKey('table1.global_id'), primary_key=True)
table2_val1 = Column(String)
table2_val2 = Column(String)
from sqlalchemy.orm import sessionmaker
some_engine = create_engine('sqlite://')
Base.metadata.create_all(some_engine)
Session = sessionmaker(bind=some_engine)
session = Session()
session.add(Table1(table1_val1='1val1',table1_val2='1val2',r1=[Table2(table2_val1='2val1', table2_val2='2val2')]))
session.commit() # expires the attribute from the session
query = session.query(Table1).options(
# note that the 'load_only()' is applied to the 'joinedload' path, not
# put on its own Load() path
joinedload('r1',innerjoin=True).load_only('table2_val1'),
Load(Table1).load_only('table1_val1'))
foo = query.all()
assert 'table1_val2' not in foo[0].__dict__
assert 'table2_val2' not in foo[0].r1[0].__dict__

Related

Returning SQLAlchemy ORM Mapped Class Check Constraint

Given the following table:
from sqlalchemy import Column, Text, Integer, CheckConstraint
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class TestTable(Base):
__tablename__ = 'my_test_table'
id = Column(Integer, primary_key=True)
name = Column(Text, CheckConstraint("name IN ('abc', 'def', 'ghi')"))
Is it possible to return a list of values in the check constraint?
My guess is that it would look something like this:
list_of_possible_names = TestTable.name.checkconstraint.values
I think you'd have to parse the check constraint text yourself but you can get it with something like:
Inspector.get_check_constraints
from sqlalchemy import inspect
# engine = ...
from sqlalchemy import Column, Text, Integer, CheckConstraint
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class TestTable(Base):
__tablename__ = 'my_test_table'
id = Column(Integer, primary_key=True)
name = Column(Text, CheckConstraint("name IN ('abc', 'def', 'ghi')"))
Base.metadata.create_all(engine)
insp = inspect(engine)
for ck in insp.get_check_constraints(TestTable.__table__):
print(ck)
{'name': 'my_test_table_name_check', 'sqltext': "name = ANY (ARRAY['abc'::text, 'def'::text, 'ghi'::text])"}

sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column could not find table

Im trying to create a relationship between two tables which are in separated classes.
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String(50))
age = Column(Integer)
So I want to create a table called order which FK is the user id.
I did this:
from sqlalchemy import (Column, Float, ForeignKey, Integer, String,
create_engine)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker
engine = create_engine(
"mysql+pymysql://root:admin#localhost/test", echo=False)
Session = sessionmaker(bind=engine)
session = Session()
Base = declarative_base()
class Order(Base):
__tablename__ = 'order'
product = Column(String(50))
price = Column(Float)
user_id = Column(
Integer,
ForeignKey('user.id', ondelete='CASCADE'), primary_key=True,
nullable=False,
# no need to add index=True, all FKs have indexes
)
cliente = relationship('User', foreign_keys='Order.user_id')
Base.metadata.create_all(engine)
I get this error:
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'order.user_id' could not find table 'user' with which to generate a foreign key to target column 'id'
you need to add db.relationship in User table not in order table hopefully you get this useful.

SQLAlchemy error relation "table_name" does not exist

Im trying to build tables with many-to-many relationship from my models file, but I'm getting error:
relation "Cities" does not exist
I think that there is an issue with my many-to-many relationship because one-to-many worked fine.
Models.py file:
from sqlalchemy import Column, String, Integer, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import backref, relationship
from sqlalchemy.sql.schema import ForeignKey
base = declarative_base()
cities_sensors = Table('cities_sensors', base.metadata,
Column('cities_id', ForeignKey('Cities.id')),
Column('sensors_id', ForeignKey('Sensors.id'))
)
class Cities(base):
__tablename__ = 'Cities'
id = Column(Integer, unique=True, primary_key=True)
name = Column(String)
sensors = relationship(
'Sensors', secondary=cities_sensors)
class Sensors(base):
__tablename__ = 'Sensors'
id = Column(Integer, unique=True, primary_key=True)
name = Column(String)
unit = Column(String)
db_init.py file:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, session
from sqlalchemy.orm.session import Session
from models import Cities, Sensors
from sqlalchemy.ext.declarative import declarative_base
db_string = "postgresql://postgres:1234#localhost:5438"
db = create_engine(db_string)
base = declarative_base()
Session = sessionmaker(db)
session = Session()
base.metadata.create_all(db)
czestochowa_city = Cities(name="Czestochowa")
myszkow_city = Cities(name="Myszkow")
krzepice_city = Cities(name="Krzepice")
temperature_sensor = Sensors(name="temperature",
unit="Celsius")
humidity_sensor = Sensors(name="humidity",
unit="precentage")
pollution_sensor = Sensors(name="pollution",
unit="PM2.5")
session.add(czestochowa_city)
session.add(myszkow_city)
session.add(krzepice_city)
session.add(temperature_sensor)
session.add(humidity_sensor)
session.add(pollution_sensor)
session.commit()
Do you guys see what I'm doing here wrong?

sqlalchemy: Inserting into joined tables

I try to add a record to a joined-inheritance table.
For some reason I cannot fathom, the dependent table is not INSERTed into.
## Inheritance test case.
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.orm import Session, relationship, backref
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Employee(Base):
__tablename__ = 'personnel'
__mapper_args__ = { 'polymorphic_on': 'etyp' }
id = Column(Integer, primary_key=True)
name = Column(String(50))
etyp = Column(String(10))
class Engineer(Employee):
__mapper_args__ = { 'polymorphic_identity':'eng' }
__tablename__ = "engineers"
id = Column(Integer, ForeignKey(Employee.id), index=True)
eng_data = Column(String(50))
engine = create_engine('sqlite:///', echo=True)
Base.metadata.create_all(engine)
session = Session(bind=engine)
e1 = Engineer(name="wally", eng_data="lazy guy")
session.add(e1)
session.commit()
# note that the Engineer table is not INSERTed into
e1 = session.query(Employee).filter_by(name="wally").one()
# the next line triggers an exception because it tries to lookup
# the Engineer row, which is missing
print e1.eng_data
This is Python 2.7, sqlalchemy 0.9.4 (Debian testing).
Making engineers.id a primary key will solve the problem:
class Engineer(Employee):
# ...
id = Column(Integer, ForeignKey(Employee.id), primary_key=True)

SQLAlchemy: mapping multi tables and relationship

There are some models:
from sqlalchemy import create_engine, Table, Column, Integer, \
String, MetaData, join, ForeignKey, select
from sqlalchemy.orm import sessionmaker, column_property, relationship
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine('sqlite:///memory')
s = sessionmaker(bind = engine)()
Base = declarative_base()
metadata = MetaData()
class BaseItem(Base):
__tablename__ = 'base_item'
id = Column(Integer, primary_key=True)
name = Column(Integer)
class Stats(Base):
__tablename__ = 'stats'
id = Column(Integer, primary_key=True)
base_item_id = Column(ForeignKey('base_item.id'))
key = Column(String(60))
value = Column(Integer)
class ItemProxy(Base):
__tablename__ = 'item_proxy'
id = Column(Integer, primary_key=True)
base_item_id = Column(ForeignKey('base_item.id'))
some = Column(Integer)
bonus_item_id = Column(ForeignKey('base_item.id'))
class Item(Base):
__table__ = BaseItem.__table__.join(ItemProxy.__table__, ItemProxy.__table__.c.base_item_id == BaseItem.__table__.c.id)
id = ItemProxy.__table__.c.id
base_id = column_property(BaseItem.__table__.c.id, ItemProxy.__table__.c.base_item_id)
stat = relationship('Stats')
bonus_stat = relationship('Stats', ???)
The model ItemProxy bonus_item_id field will not be filled at all times.
What you need to specify a relationship that would have made it the correct query?

Categories

Resources