"Irregular" SQL function in SqlAlchemy - python

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

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?

ArgumentError: Mapper mapped class Users->users could not assemble any primary key columns for mapped table 'users'

I am new to SQLAlchemy. Trying to build database in Heroku Postgres
Get error:
ArgumentError: Mapper mapped class Users->users could not assemble any primary key columns for mapped table 'users'
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import (Column, Integer, BigInteger, String, Sequence, TIMESTAMP, Boolean, JSON)
from sqlalchemy import sql
from sqlalchemy import Table, Column, Integer, String, MetaData, Sequence, create_engine
class Users(Base):
__tablename__ = 'users'
meta = MetaData()
users_table = Table(
'users', meta,
Column('id', Integer, primary_key=True),
Column('name',String(50)),
Column('fullname',String(50)),
Column('phone',Integer),
)
meta.create_all(engine)
def __repr__(self):
return "<User(id='{}', fullname='{}', username='{}')>".format(
self.id, self.full_name, self.username)
The main reasons this does not work is that you try to create the table before the class User is created AND also the table you declare is not declared on the correct attribute. So sqlalchemy cannot find the id column.
I have tried to outline a more idiomatic declarative approach below:
# This implicitly creates metadata, you do not need to make an explicit one.
Base = declarative_base()
class Users(Base):
__tablename__ = 'users'
# Using a table explicitly is not required here
# Just declare the columns as properties.
id = Column(Integer, primary_key=True)
name = Column(String(50))
fullname = Column(String(50))
phone = Column(Integer)
# Don't do this here because Users is not done
# meta.create_all(engine)
def __repr__(self):
return "<User(id='{}', fullname='{}', username='{}')>".format(
self.id, self.full_name, self.username)
# Do this after classes are declared and use Base's metadata.
Base.metadata.create_all(engine)
References:
If you really want to set a table you have to set it with __table__ and use Base.metadata:
https://docs.sqlalchemy.org/en/13/orm/extensions/declarative/table_config.html#using-a-hybrid-approach-with-table

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