I am using the SQLModel library to do a simple select()
like described on their official website. However I am getting Column expression or FROM clause expected
error message
from typing import Optional
from sqlmodel import Field, Session, SQLModel, create_engine, select
from models import Hero
sqrl = f"mysql+pymysql:///roo@asdf:localhost:3306/datab"
engine = create_engine(sqrl, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def select_heroes():
with Session(engine) as session:
statement = select(Hero)
results = session.exec(statement)
for hero in results:
print(hero)
def main():
select_heroes()
if __name__ == "__main__":
main()
this is my models/Hero.py
code:
from datetime import datetime, date, time
from typing import Optional
from sqlmodel import Field, SQLModel
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
created: datetime
lastseen: time
when I run app.py I get the sqlalchemy.exc.ArgumentError: Column expression or FROM clause expected, got <module 'models.Hero' from '/Users/dev/test/models/Hero.py'>.
message
The error message <Column expression or FROM clause expected, got module 'models.Hero' from '/Users/dev/test/models/Hero.py'>
tells us:
models.Hero
Hero.py
The solution is to replace the object causing the error with something that the select
or query
function would expect to receive, such as an SQLAlchemy or SQLModel ORM model class.
The import statement from models import Hero
only imports the module Hero
. Either
from models.Hero import Hero
select_heroes
to reference the model†
statement = select(Hero.Hero)
* It's conventional to use all lowercase for module names; following this convention will help you distinguish between modules and models.
† This approach is preferable in my opinion: accessing the object via the module namespace eliminates the possibility of name collisions (of course it can be combined with lowercase module names).