简体   繁体   中英

Select from table defined by SQLAlchemy declarative_base

I am working on FastAPI tutorial and I am trying to create tables using SQLAlchemy+Alembic+ databases .
In my main.py I have:

from typing import List

import databases
import sqlalchemy
from fastapi import FastAPI
from pydantic import BaseModel
from sqlalchemy import Table

DATABASE_URL = "sqlite:///./test.db"

database = databases.Database(DATABASE_URL)
metadata = sqlalchemy.MetaData()

notes = sqlalchemy.Table(
    "note",
    metadata,
    sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True),
    sqlalchemy.Column("text", sqlalchemy.String),
    sqlalchemy.Column("completed", sqlalchemy.Boolean),
)

class Note2(BaseModel):
    id: int
    text: str
    completed: bool

app = FastAPI()

@app.on_event("startup")
async def startup():
    await database.connect()

@app.on_event("shutdown")
async def shutdown():
    await database.disconnect()

@app.get("/notes/", response_model=List[Note2])
async def read_notes():
    query = notes.select()
    return await database.fetch_all(query)

And this works - I can GET /notes/ endpoint. But it looks newbie to create a datatabase table in the same module with endpoints, so I decided to make models.py file and create a normal model there, like this:

import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Note(Base):
    __tablename__ = "note"

    id = sa.Column(sa.Integer, primary_key=True)
    text = sa.Column(sa.String)
    completed = sa.Column(sa.Boolean)

And here comes a problem - when I change the endpoint like this:

from app_second.models import Note

@app.get("/notes/", response_model=List[Note2])
async def read_notes():
    query = Note().select()
    return await database.fetch_all(query)

I recieve an error:

AttributeError: 'Note' object has no attribute 'select'

As it is mentioned here - declarative_base() is just a syntactic shugar for Table + mapper . But what is the right way to select/filter/update tables declared that way?

You can use the table property to access the table methods and then use database.fetch_all() or similar. Eg:

from sqlalchemy import select
    
...
skip = 0
limit = 100

query = (
    Note.__table__.select()
    .offset(skip)
    .limit(limit)
)
return await database.fetch_all(query)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM