feel free to hang here, note that some of the "chat" happens on libera.chat #sqlalchemy
Hi all,
It has been only a while since I've started tinkering with SQLAlchemy. I aws working on a particular requirement of mine, where I had 4 types of users with login functionality. But each type has different attributes.
The user types are : Client, Brand, Merchant, Customer. All these types were supposed to have login access to the system. I created a parent model called User and other models like Client, Brand, Merchant and Customer inherits from the User model. I implemented it using joined table inheritance as per the documentation.
============================================================
class User(UserMixin, BaseModel):
__tablename__ = "users"
id = Column(Integer, primary_key=True, autoincrement=True, unique=True)
email = Column(String, unique=True, nullable=False, index=True)
confirmed = Column(Boolean, default=False, nullable=False)
role = Column(Enum(Role))
__mapper_args__ = {
"polymorphic_on": role,
}
=============================================================
class Client(User):
__tablename__ = "clients"
id = Column(Integer, ForeignKey("users.id"), primary_key=True)
__mapper_args__ = {
"polymorphic_identity": "client",
'inherit_condition': (id == User.id)
}
client_data = (...)
.....
================================================================
class Brand(User):
__tablename__ = "brands"
id = Column(Integer, ForeignKey("users.id"), primary_key=True)
__mapper_args__ = {
"polymorphic_identity": "brand",
'inherit_condition': id == User.id
}
brand_data = (...)
.....
Then I created an User object, which is to serve as the admin user. It works fine and well.
But the problem is when I'm creating other user types. For eg: when I'm creating a Client object, a row is created in the Client table as well as the User table. I am able to login with the client user. But the problem is when I'm trying to access the Client object's attributes. And the object type returned while querying the Client is of type User.
>>> from src.models.models import User
>>> User.get_all()
[<User 63: xxxxxxx>, <User 7: xxxxxxx>, <User 67: xxxxxxxx>, <User 13: xxxxxxxx>, <User 69: xxxxxxxxx>, <User 72: xxxxxxxx>]
>>> from src.models.models import Client
>>>
>>> Client.get_all()
[<User 7: xxxxxx>, <User 67: xxxxxxx>, <User 69: xxxxxx>]
>>>
But if I'm making the query on Client object before loading the User, it returns fine.
>>> from src.models.models import Client
>>> Client.get_all()
[<Client xxxxx>, <Client xxxxxxx>, <Client xxxxxx>]
>>>
I feel like I'm missing out on something?
I am struggling with some async session/connection issues with asyncpg with 1.4.26. I have the following:
async_session: sessionmaker = sessionmaker(
bind=engine,
class_=AsyncSession,
autocommit=False,
autoflush=False,
expire_on_commit=False,
)
...
async with async_session() as db:
...
an_obj.update_list_words(db, myman)
...
async def update_list_words(
self, db: AsyncSession, manager: EnrichmentManager
):
...
for freq, word in word_list:
data.append(UserListDict(word=word, import_frequency=int(freq)))
temp_table = f"import_{self.id}".replace("-", "_") # self.id is a GUID
sql = f"""CREATE TEMP TABLE {temp_table} (word text, import_frequency int, word_id int null, freq float null)"""
await db.execute(text(sql))
await db.execute(text( f"""INSERT INTO {temp_table} (word, import_frequency) values (:word, :import_frequency) """), data,)
await db.execute(text(
f"""UPDATE {temp_table}
SET word_id = mitable.id
FROM mitable
WHERE word = mitable.source_text
and mitable.from_lang = :from_lang
and mitable.to_lang = :to_lang"""
),
{"from_lang": manager.from_lang, "to_lang": manager.to_lang},
)
...
await db.execute(text(f"DROP TABLE {temp_table}"))
await db.commit()
I am getting some strange behaviour that I just can't understand. For example, I just got a 'asyncpg.exceptions.UndefinedTableError'>: relation "import_19fd0dbb_0321_4124_a810_22a4efee7ab1" does not exist
when it gets to the UPDATE which I am struggling to understand how it's possible. Any pointers? It works sometimes, typically the first time it gets called. Then it fails with a few different errors.
with Session.begin() as session:
while has_remaining_operations():
operations = session.query(Operation) \
.filter(
Operation.id_user == user.id and
Operation.processed_at is None
) \
.order_by(Operation.created_at.asc()) \
.limit(100) \
.all()
for op in operations:
# code to execute
op.processed_at = datetime.now().isoformat()
processed_at
modification doesn't get applied when session.query
is executed
Operation.created_at
, grab the last one from each chunk and add a WHERE Operation.created_at > last_created_at_from_previous_chunk
.filter
clause. It should have looked like this: .filter(and_(
SavedOp.id_user == user.id,
SavedOp.processed_at.is_(None)
)) \
is_(None)
is the correct form
await session.execute(
sqlalchemy.update(
some_table
).where(
some_table.id.in_(ids)
).values(
[{'a':.., ...}, {'a':.., ...},...]
),
)
UPDATE construct does not support multiple parameter sets.
cursor.execute(statement, parameters)
where cursor
is a psycopg2 cursor
parameters
is an empty dict
cur.execute('select 1', {})
where type(cur)
is psycopg2.extensions.cursor