Returning SQLAlchemy ORM Mapped Class Check Constraint - python

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])"}

Related

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.

"Irregular" SQL function in SqlAlchemy

In SqlAlchemy ORM how can I use a SQL function which requires keywords along with arguments, for example, POSITION(substr IN str). The following doesn't work:
from sqlalchemy import Column, Integer, String, select
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class SomeClass(Base):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)
name = Column(String(50))
sel = select(SomeClass).where( POSITION('x' IN name) > 5 ) # doesn't work

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?

Self-Referential Many-to-Many Relationship with Association Proxy in SQLAlchemy

I'm trying to create a Self-Referential Many-to-Many Relationship. The example outlined in the SQLAlchemy documentation works great. Here are the models I created:
from sqlalchemy import Integer, ForeignKey, String, Column, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
Base = declarative_base()
Table('NodeToNode', Base.metadata,
Column('leftNodeId', Integer, ForeignKey('Node.id'), primary_key=True),
Column('rightNodeId', Integer, ForeignKey('Node.id'), primary_key=True)
)
class Node(Base):
__tablename__ = 'Node'
id = Column(Integer, primary_key=True)
label = Column(String)
rightNodes = relationship('Node',
secondary='NodeToNode',
primaryjoin='Node.id==NodeToNode.c.leftNodeId',
secondaryjoin='Node.id==NodeToNode.c.rightNodeId',
backref='leftNodes'
)
And the script for adding data in:
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
engine = create_engine('sqlite:///practice.sqlite3')
session = Session(bind=engine)
nodes = [
Node(label='A'),
Node(label='B'),
Node(label='C'),
Node(label='D'),
Node(label='E'),
]
nodes[0].rightNodes = [nodes[1], nodes[3], nodes[2]]
nodes[0].leftNodes = [nodes[4]]
session.add_all(nodes)
session.commit()
I want to add a column to the association table so I'd assume I need to convert the association table to its own class:
class NodeToNode(Base):
__tablename__ = 'NodeToNode'
leftNodeId = Column(Integer, ForeignKey('Node.id', onupdate='CASCADE'), primary_key=True)
rightNodeId = Column(Integer, ForeignKey('Node.id', onupdate='CASCADE'), primary_key=True)
sortOrder = Column(Integer, nullable=False)
This, however, results in the following error:
sqlalchemy.exc.InvalidRequestError: Class <class 'models.node.NodeToNode'> does not have a mapped column named 'c'
Any idea what I'm doing wrong here?

Load subset of joined columns in SQLAlchemy

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__

Categories

Resources