question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

SQLModel: Many-to-many relationship data dropped when paginating

See original GitHub issue

This is similar to https://github.com/uriyyo/fastapi-pagination/issues/294

However, when using SQLModel the relationship data is dropped. I’m always getting null for tags in my FastAPI response.

The queries seem fine. If I remove pagination, a simple unpaginated List of CustomerViews contains the tags. Maybe I’m doing something wrong with the model setup?

Excuse typos / weirdness. I had to pull this out of a large project and pare it down to make it readable.


# Relevant schema classes ----------------------------------------------

class CustomerViewToTagBase(SQLModel, TimeStampMixin):
    customer_view: int = Field(foreign_key="customer_view.id", primary_key=True)
    tag: int = Field(foreign_key="tag.id", primary_key=True)

class CustomerViewToTag(CustomerViewToTagBase, table=True):
    __tablename__ = "customer_view_to_tag"

class TagBase(SQLModel):
    name: str

class Tag(TagBase, table=True):
    __tablename__ = "tag"
    id: Optional[int] = Field(default=None, primary_key=True)
    customer_views: List["CustomerView"] = Relationship(back_populates="tags", link_model=CustomerViewToTag)

class CustomerViewBase(SQLModel):
    __tablename__ = "customer_view"
    name: Optional[str] = Field(default=None)

class CustomerView(CustomerViewBase, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    tags: List["Tag"] = Relationship(back_populates="customer_views", link_model=CustomerViewToTag)

# For FastAPI
class CustomerViewWithTag(CustomerViewBase):
    id: int
    tags: Optional[List[Tag]]

    # I have no idea if this is necessary, I added it based on the linked issue above #294 
    class Config:
        orm_mode = True


# Router ------------------------------------------------------------------------

@router.get("/withtags", response_model=Page[CustomerViewWithTag], status_code=200)
async def get_customer_views_with_tags(
        db_session: AsyncSession = Depends(get_db_session),
        params: Params = Depends(),
        filter: Optional[str] = None
    ):
    async with db_session as db:
        customerviews_query = select(CustomerView).order_by(CustomerView.id).options(selectinload(CustomerView.tags))

        if filter is not None:
            customerviews_query = customerviews_query.filter(
                    CustomerView.name.ilike('%' + filter + '%')
            )

        # Switching the response_model to a List and the following code makes the relationship work properly
        # res = await db.execute(customerviews_query)
        # return res.scalars().all()
        return await paginate(session=db, query=customerviews_query, params=params)

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
thebleucheesecommented, May 5, 2022

Hi @thebleucheese,

I will take a closer look

Thanks!

I’ll try to dig into it some more this weekend to see if I can find a fix unless you beat me to it.

PS - I love the project, it’s helped a lot with my first foray into using FastAPI

0reactions
uriyyocommented, Jun 5, 2022

@thebleucheese Thanks for such a detailed investigation. I will close this ticket. Please, reopen it in case you still have some issues.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Many to Many - Intro - SQLModel - tiangolo
We saw how to work with One-to-Many relationships in the data. But how do you handle Many-to-Many relationships? Let's explore them.
Read more >
Update and Remove Many-to-Many Relationships - SQLModel
Now we'll see how to update and remove these many-to-many relationships. ... I'll use the short version and get the data in a...
Read more >
Read a Range of Data - LIMIT and OFFSET - SQLModel
This is commonly called "pagination". Because the user interface would normally show a "page" of a predefined number of heroes at a time....
Read more >
Create Models with a Many-to-Many Link - SQLModel
Let's start by defining the class models, including the link table model. Link Table Model¶. As we want to support a many-to-many relationship,...
Read more >
Create Data with Many-to-Many Relationships - SQLModel
Let's continue from where we left and create some data. We'll create data for this same many-to-many relationship with a link table: many-to-many...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found