collerek/ormar

FastpAPI state has not database

Closed this issue ยท 4 comments

Hello everyone

There is a problem using ormar with fastapi,
database_ = app.state.database

my complete code:
async def connect_database(app: FastAPI) -> None:
database_ = app.state.database
if not database_.is_connected:
await database_.connect()

async def disconnect_database(
app: FastAPI,
) -> None:
database_ = app.state.database
if database_.is_connected:
await database_.disconnect()

the code will raise the error:
^^^^^^^^^^^^^^^^^^
File "C:\Users\example\AppData\Local\pypoetry\Cache\virtualenvs\backend-wTk0BbyO-py3.11\Lib\site-packages\starlette\datastructures.py", line 705, in __getattr__ raise AttributeError(message.format(self.__class__.__name__, key)) AttributeError: 'State' object has no attribute 'database'

while adding the above to the on event start it raise the following error

Versions (please complete the following information):

  • Database backend used postgress
  • Python version : ^3.11
  • ormar version : "^0.12.2"
  • pydantic version : >=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0
  • if applicable fastapi version : 0.98.0 || 1.00.0

Additional context
Add any other context about the problem here.

dekoza commented

You did not setup the database. You probably missed the step where you assign the db to app's state.

But nevertheless the method proposed in ormar documentation is obsolete as per FastAPI standards. Currently the correct way is to use FastAPI's lifespan events:

First, define your lifespan asynccontextmanager:
File lifespan.py

from contextlib import asynccontextmanager

from fastapi import FastAPI


@asynccontextmanager
async def lifespan(app: FastAPI):
    # startup actions
    if not app.state.database.is_connected:
        await app.state.database.connect()

    yield

    if app.state.database.is_connected:
        await app.state.database.disconnect()

then use it in main.py like this:

import databases
import sqlalchemy
import os
from .lifespan import lifespan

#database config
database_url = os.environ["DATABASE_URL"]

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


# core
app = FastAPI(title="My App", lifespan=lifespan)
app.state.database = database  # <- important!

# the rest of your app's setup
...

Thanks @dekoza for replying, ubfortuniatly the error still comes up

if not app.state.database.is_connected:
^^^^^^^^^^^^^^^^^^
File "C:\Users\owoni\AppData\Local\pypoetry\Cache\virtualenvs\backend-wTk0BbyO-py3.11\Lib\site-packages\starlette\datastructures.py", line 705, in getattr
raise AttributeError(message.format(self.class.name, key))
AttributeError: 'State' object has no attribute 'database'

dekoza commented

@Kokoserver please make sure you've attached the database to app's state. See my example, line marked with "important!"

@dekoza thanks Very much it works now ๐Ÿ™Œ๐Ÿ™Œ๐Ÿ™Œ๐Ÿ‘Œ