Skip to content

Relationship attribute not in model schema #255

Description

@carlosporta

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 SQLModel documentation, with the integrated search.
  • I already searched in Google "How to X in SQLModel" 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 SQLModel but to Pydantic.
  • I already checked if it is not related to SQLModel but to SQLAlchemy.

Commit to Help

  • I commit to help with one of those options 👆

Example Code

from fastapi import FastAPI
from sqlmodel import Field, Relationship, SQLModel, create_engine, Session, select


class Child(SQLModel, table=True):
    __tablename__ = "child"
    id: int = Field(default=None, primary_key=True)
    parent_id: int = Field(default=None, foreign_key="parent.id")
    parent: "Parent" = Relationship(back_populates="children")


class Parent(SQLModel, table=True):
    __tablename__ = "parent"
    id: int = Field(default=None, primary_key=True)
    children: List[Child] = Relationship(
        back_populates="parent",
        sa_relationship_kwargs={"lazy": "joined"},
    )


engine = create_engine("sqlite:///./test.db", connect_args={'check_same_thread': False})
SQLModel.metadata.drop_all(engine)
SQLModel.metadata.create_all(engine)
with Session(engine) as session:
    session.add(Parent(id=0))
    session.add(Child(id=0, parent_id=0))
    session.add(Child(id=1, parent_id=0))
    session.commit()


app = FastAPI()
@app.get("/parent", response_model=Parent)
def get_parent():
    with Session(engine) as session:
        parent = session.exec(select(Parent)).first()
        print(parent)
        # id=0 children=[Child(parent_id=0, id=0), Child(parent_id=0, id=1)]
        return parent


print(Parent.schema())
# {'title': 'Parent', 'type': 'object', 'properties': {'id': {'title': 'Id', 'type': 'integer'}}}
# Repare that there is no children attribute

Description

I have two related models (one parent to many children). And that relationship is eager, as you can see when I select a parent and print it, it is possible to see its children too. But the problem happens when I want to cast the result from the select statement to a parent model, using for example the from_orm function, because there is no attribute named children on the parent schema. My problem is probably related to this issue: #224.

Operating System

Windows

Operating System Details

No response

SQLModel Version

0.0.6

Python Version

3.10.2

Additional Context

No response

Activity

  1. 4linuxfun commented on Mar 21, 2022

    @4linuxfun

    I think it's useful,you can see the doc :https://sqlmodel.tiangolo.com/tutorial/fastapi/relationships/

  2. AdamMisiak commented on Jun 8, 2022

    @AdamMisiak

    Hey @carlosporta!
    I am facing very similar issue right now. Did you manage to solve this? :)

  3. AverageFazeFan commented on Jun 9, 2022

    @AverageFazeFan

    @AdamMisiak
    I had a problem where relationship attributes would not appear at all. Aparently SQLAlchemy 1.4.36 (current version is 1.4.37) breaks relationships (source).

    I installed version 1.4.35 and it fixed my issue, hope it fixes yours too!

  4. kiddten commented on Jun 20, 2022

    @kiddten

    same issue here

  5. tiangolo commented on Aug 27, 2022

    @tiangolo
    Member

    Hey there @carlosporta! You need to declare a model that explicitly includes the children for the response_model, otherwise you could end up with infinite recursion.

    As @4linuxfun says, you can read the docs explaining it, the relevant section is here: https://sqlmodel.tiangolo.com/tutorial/fastapi/relationships/#dont-include-all-the-data


    About the issue mentioned by @alp09, that one is reported here: #315, it was solved here: #322, it will be available in the next version, in a couple of hours, SQLModel 0.0.7.

  6. koldakov commented on Oct 23, 2024

    @koldakov

    @tiangolo

    1. I'm using sqlmodel to reduce mappings between sqlalchemy models/pydantic models
    2. I can't use response_model as I'm using template responses and need to model dump to context ( aka problem 1 )

    Currently what I did is:

    from sqlmodel import SQLModel as _SQLModel
    
    class SQLModel(_SQLModel):
        """Base Model Class."""
    
        def model_dump(self, ...):
            ""Some magic happens here""
    

    Also there is a method I've written for pagination that is available for table=True objects, which returns Page[SQLModel], so there is no way of mapping WhateverModel to WhateverModelWithRelations without extra magic

    So as you understand that's not the ideal solution.

    Also I've looked into the code and as I understand you don't add Relation fields as real fields that's why it doesn't work, but in fact there is no need to load relations by default cause it leads to the extra DB requests, so maybe it does make sense to limit recursion level ( for example, as it's done in sqlalchemy - recursion_depth )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    answeredquestionFurther information is requested

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions