Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dynamic='lazy' in SQLAlchemy relationship causes FastAPI to stack overflow #3886

Closed
9 tasks done
Tears opened this issue Sep 10, 2021 · 8 comments
Closed
9 tasks done
Labels
question Question or problem question-migrate

Comments

@Tears
Copy link

Tears commented Sep 10, 2021

First Check

  • I added a very descriptive title to this issue.
  • I used the GitHub search to find a similar issue and didn't find it.
  • I searched the FastAPI documentation, with the integrated search.
  • I already searched in Google "How to X in FastAPI" and didn't find any information.
  • I already read and followed all the tutorial in the docs and didn't find an answer.
  • I already checked if it is not related to FastAPI but to Pydantic.
  • I already checked if it is not related to FastAPI but to Swagger UI.
  • I already checked if it is not related to FastAPI but to ReDoc.

Commit to Help

  • I commit to help with one of those options 👆

Example Code

See description

Description

Hi,

I hope you are all well. I'm using FastAPI in combination with SQLAlchemy, so I'm not really sure if I should post this there or here, but from the logs it seems that FastAPI is causing the stack overflow.

I have the following defined in my Student-model:

notes = relationship("Note", back_populates="student", lazy='dynamic')

And this is my function in the router which when I run it causes the stack overflow:

@router.get("/view/{student_id}/notes", response_model=Optional[List[BaseNote]])
async def view_student_notes(student: Student = Permission("view", find_student)):

    notes = student.notes.filter(Note.is_active == True)

    return notes

This is the error that is being generated upon running the function above:

Fatal Python error: _Py_CheckRecursiveCall: Cannot recover from stack overflow.
Python runtime state: initialized

Thread 0x0000700007b1a000 (most recent call first):
  File "/usr/local/Cellar/python@3.9/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/concurrent/futures/thread.py", line 75 in _worker
  File "/usr/local/Cellar/python@3.9/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 910 in run
  File "/usr/local/Cellar/python@3.9/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 973 in _bootstrap_inner
  File "/usr/local/Cellar/python@3.9/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 930 in _bootstrap

Current thread 0x000000010a539e00 (most recent call first):
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/sqlalchemy/sql/operators.py", line 434 in __getitem__
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/sqlalchemy/sql/elements.py", line 865 in operate
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/sqlalchemy/sql/operators.py", line 434 in __getitem__
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/sqlalchemy/orm/properties.py", line 430 in operate
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/sqlalchemy/sql/operators.py", line 434 in __getitem__
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/sqlalchemy/orm/attributes.py", line 317 in operate
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/sqlalchemy/sql/operators.py", line 434 in __getitem__
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 137 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 93 in jsonable_encoder
  File "/Users/user/.local/share/virtualenvs/try_core_api-gYx03z5k/lib/python3.9/site-packages/fastapi/encoders.py", line 145 in jsonable_encoder
  ...

Once again, not sure if it's FastAPI, but it seems that way. Thanks in advance!

Operating System

macOS

Operating System Details

No response

FastAPI Version

0.68.1

Python Version

Python 3.9.7

Additional Context

No response

@Tears Tears added the question Question or problem label Sep 10, 2021
@Kludex
Copy link
Sponsor Collaborator

Kludex commented Sep 10, 2021

Can you provide a minimal working example?

@Tears
Copy link
Author

Tears commented Sep 10, 2021

Can you provide a minimal working example?

models/student.py

import json
import uuid
from datetime import datetime

from sqlalchemy import Boolean, Column, DateTime, ForeignKey, Integer, String, Table
from sqlalchemy.dialects.postgresql import JSON
from sqlalchemy.orm import Session, relationship

from database import Base


class Student(Base):
    __tablename__ = "students"

    name = Column(String)
    notes = relationship("Note", back_populates="student", dynamic='lazy')

routers/student.py

from typing import List, Optional

from fastapi import APIRouter, Depends, HTTPException

from database import get_db
from helpers.finders import *
from models.note import Note
from models.student import Student
from oauth_helpers import get_current_active_user
from permissions import Permission
from schemas.notes import BaseNote

router = APIRouter()


@router.get("/view/{student_id}/notes", response_model=Optional[List[BaseNote]])
async def view_student_notes(student: Student = Permission("view", find_student)):

    notes = student.notes.filter(Note.is_active == True)

    return notes

schemas/notes.py

from datetime import datetime
from typing import List, Optional

from pydantic import BaseModel

class BaseNote(BaseModel):

    id: int
    content: str
    created_at: datetime
    updated_at: datetime
    attachment: Optional[str]

    class Config:
        orm_mode = True

models/note.py

from typing import List

from fastapi import Depends
from datetime import datetime
from sqlalchemy import Boolean, Column, Integer, String, Text, ForeignKey, DateTime
from sqlalchemy.orm import Session, relationship

from database import Base


class Note(Base):
    __tablename__ = "notes"

    id = Column(Integer, primary_key=True, autoincrement=True)
    content = Column(Text, nullable=False)
    created_at = Column(DateTime, default=datetime.now, nullable=False)
    last_updated = Column(
        DateTime, default=datetime.now, onupdate=datetime.now, nullable=False
    )
    is_active = Column(Boolean, default=True, nullable=False)

    student_id = Column(Integer, ForeignKey("students.id"))
    student = relationship("Student", back_populates="notes")

    attachment = Column(String)

I think these are all the relevant files.

@Tears
Copy link
Author

Tears commented Sep 24, 2021

Any updates? Any relationship where lazy='dynamic' is defined creates a stack overflow in FastAPI.

@Kludex
Copy link
Sponsor Collaborator

Kludex commented Sep 24, 2021

Maybe this helps? #194 🤔

@Tears
Copy link
Author

Tears commented Oct 6, 2021

Maybe this helps? #194 🤔

Thank you, but orm_mode = True does unfortunately not fix the problem.

@Tears
Copy link
Author

Tears commented Oct 27, 2021

Bump. We really need to solve this before we can continue our project. @Kludex - do you need any additional information from us?

@Tears
Copy link
Author

Tears commented Oct 27, 2021

Another example:

models/user.py:

class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, autoincrement=True)
    first_name = Column(String, nullable=False)
    last_name = Column(String, nullable=False)
    notifications = relationship("Notification", back_populates="user")

schemas/users.py:

class BaseUser(BaseModel):

    id: int
    first_name: str
    last_name: str

    class Config:
        orm_mode = True

models/notification.py:

class Notification(Base):
    __tablename__ = "notifications"

    id = Column(Integer, primary_key=True, autoincrement=True)
    subject = Column(String, nullable=False)
    body = Column(Text, nullable=False)
    is_read = Column(Boolean, default=False, nullable=False)

    user_id = Column(Integer, ForeignKey("users.id"))
    user = relationship("User", back_populates="notifications")

schemas/notifications.py:

class BaseNotification(BaseModel):

    id: int
    subject: str
    body: str
    is_read: bool
    user: BaseUser

    class Config:
        orm_mode = True

routers/users.py:

@router.get("/user/notifications", response_model=Optional[List[BaseNotification]])
async def get_notifications(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):

    return current_user.notifications

This works like expected. However, when we want to filter to only show the unread notifications to the user, things start to act crazy. We make the following changes:

models/user.py:

class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, autoincrement=True)
    first_name = Column(String, nullable=False)
    last_name = Column(String, nullable=False)

     # We add lazy="dynamic" to enable filtering on related objects (see: https://docs.sqlalchemy.org/en/14/orm/collections.html#dynamic-relationship-loaders)
    notifications = relationship("Notification", back_populates="user", lazy="dynamic")

routers/users.py:

@router.get("/user/notifications", response_model=Optional[List[BaseNotification]])
async def get_notifications(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):

    # Add the filtering
    return current_user.notifications.filter(Notification.is_read == False)

This causes the following error:

pydantic.error_wrappers.ValidationError: 1 validation error for BaseNotification
response
  value is not a valid list (type=type_error.list)

That is weird - nothing should be changed in the output (this user only has unread notifications). When we remove the response model to check the output, we get the stack overflow as posted in this issue.

Are we doing something wrong? Is FastAPI doing something wrong? Is SQLAlchemy doing something wrong?

@Kludex
Copy link
Sponsor Collaborator

Kludex commented Oct 27, 2021

I don't think the "dynamic" strategy can be applied, I think I've faced the same issue some time ago, but I need to recheck the jsonable_encoder.

If you want help, you should probably add a proper minimal working example i.e. that ppl can copy/paste/clone and just run.

In any case, you can check if other lazy options suits your needs.

Repository owner locked and limited conversation to collaborators Feb 28, 2023
@tiangolo tiangolo converted this issue into discussion #8819 Feb 28, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
question Question or problem question-migrate
Projects
None yet
Development

No branches or pull requests

3 participants