sqlitesqlalchemyfastapipydanticsqlmodel

Sqlmodel/Sqlalchemy: could not assemble any primary key columns for mapped table


I've tried the following in two different projects, in one it works, in the other it doesnt. I'm gonna paste here all the relevant code for the one project is does not work:

src/
  dependencies/
    __init__.py
    sqlmodel.py
  models/
    __init__.py
    student.py
  routes/
    __init__.py
    routes.py
    students.py
  main.py

main.py

from fastapi import FastAPI

from src.dependencies.sqlmodel import init_engine

def main():
    init_engine()


main()

from src.routes.routes import api_router
app = FastAPI()
app.include_router(api_router)

dependencies/sqlmodel.py

import os
from sqlmodel import SQLModel, create_engine

root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../.."))
SQLITE_FILE_PATH = os.path.join(root, "database.db")

__engine = None

def init_engine():
    global __engine
    print(SQLITE_FILE_PATH)
    __engine = create_engine(f"sqlite:///{SQLITE_FILE_PATH}", echo=True)
    SQLModel.metadata.create_all(__engine)

def get_session() -> Generator[Session, None, None]:
   with Session(__engine) as session:
       yield session
SessionDep = Annotated[Session, Depends(get_session)]

models/student.py

from pydantic import BaseModel, Field
from sqlmodel import SQLModel

class StudentBase(SQLModel):
    nombre: str
    apellido: str
    edad: int | None = Field(default=None, ge=17)

class Student(StudentBase, table=True):
    identifier: int = Field(primary_key=True)

routes/routes.py

from fastapi import APIRouter

from src.routes import students

api_router = APIRouter()
api_router.include_router(students.router, prefix="/students", tags=["students"])

So when trying to run my fastapi application I get the mentioned error ArgumentError: Mapper Mapper[Student(student)] could not assemble any primary key columns for mapped table 'student'

I have a very similar project, just with a different file structre, where all of this just works fine.

I've tried creating migrations with Alembic even, like this:

def upgrade() -> None:
   op.create_table(
       'student',
       sa.Column('identifier', sa.Integer, primary_key=True),
       sa.Column('name', sa.Text, nullable=False),
       sa.Column('last_name', sa.Text, nullable=False),
       sa.Column('age', sa.Integer)
   )

But I get the same error (I made sure the path to the sqlite db is correct in all places)


Solution

  • In models/student.py, you're importing Field from pydantic, it should be from sqlmodel:

    from sqlmodel import SQLModel, Field
    
    class StudentBase(SQLModel):
        nombre: str
        apellido: str
        edad: int | None = Field(default=None, ge=17)
    
    class Student(StudentBase, table=True):
        identifier: int = Field(primary_key=True)