<h3 dir="auto">First Check</h3>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I added a very descriptive title to this issue.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I used the GitHub search to find a similar issue and didn't find it.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I searched the FastAPI documentation, with the integrated search.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I already searched in Google "How to X in FastAPI" and didn't find any information.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I already read and followed all the tutorial in the docs and didn't find an answer.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I already checked if it is not related to FastAPI but to <a href="https://github.com/samuelcolvin/pydantic">Pydantic</a>.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I already checked if it is not related to FastAPI but to <a href="https://github.com/swagger-api/swagger-ui">Swagger UI</a>.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I already checked if it is not related to FastAPI but to <a href="https://github.com/Redocly/redoc">ReDoc</a>.</li>
</ul>
<h3 dir="auto">Commit to Help</h3>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I commit to help with one of those options <g-emoji class="g-emoji" alias="point_up_2" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f446.png">👆</g-emoji></li>
</ul>
<h3 dir="auto">Example Code</h3>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from __future__ import annotations

from dataclasses import dataclass, field

from fastapi import Depends, FastAPI
from pydantic import BaseModel
from sqlalchemy import Column, ForeignKey, Integer, String, create_engine
from sqlalchemy.orm import Session, registry, relationship, sessionmaker
from uvicorn import run

SQLALCHEMY_DATABASE_URL = &quot;sqlite:///./sql_app.db&quot;

engine = create_engine(
    SQLALCHEMY_DATABASE_URL, connect_args={&quot;check_same_thread&quot;: False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

mapper = registry()


@mapper.mapped
@dataclass
class User:
    __tablename__ = &quot;users&quot;
    __sa_dataclass_metadata_key__ = &quot;sa&quot;

    id: int = field(
        metadata={
            &quot;sa&quot;: Column(Integer, primary_key=True, index=True)
        }
    )
    email: str = field(
        metadata={
            &quot;sa&quot;: Column(String, unique=True, index=True)
        }
    )
    items: list[Item] = field(
        init=False,
        metadata={
            &quot;sa&quot;: relationship(&quot;Item&quot;, lazy=&quot;raise&quot;)
        }
    )

    @property
    def greeting(self):
        return f&quot;Hello {self.email}&quot;


@mapper.mapped
@dataclass
class Item:
    __tablename__ = &quot;items&quot;
    __sa_dataclass_metadata_key__ = &quot;sa&quot;

    id: int = field(
        metadata={
            &quot;sa&quot;: Column(Integer, primary_key=True, index=True)
        }
    )
    title: str = field(
        metadata={
            &quot;sa&quot;: Column(String, index=True)
        }
    )
    owner_id: int = field(
        init=False,
        metadata={
            &quot;sa&quot;: Column(Integer, ForeignKey(&quot;users.id&quot;))
        }
    )


class UserIn(BaseModel):
    id: int
    email: str


class UserOut(BaseModel):
    id: int
    email: str
    greeting: str

    class Config:
        orm_mode = True


mapper.metadata.create_all(bind=engine)

app = FastAPI()


def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()


@app.post(&quot;/users/&quot;, response_model=UserOut)
def create_user(user: UserIn, db: Session = Depends(get_db)):
    instance = User(
        id=user.id,
        email=user.email
    )
    db.add(instance)
    db.commit()
    return instance


if __name__ == '__main__':
    run(app)"><pre class="notranslate"><span class="pl-k">from</span> __future__ <span class="pl-k">import</span> <span class="pl-s1">annotations</span>

<span class="pl-k">from</span> <span class="pl-s1">dataclasses</span> <span class="pl-k">import</span> <span class="pl-s1">dataclass</span>, <span class="pl-s1">field</span>

<span class="pl-k">from</span> <span class="pl-s1">fastapi</span> <span class="pl-k">import</span> <span class="pl-v">Depends</span>, <span class="pl-v">FastAPI</span>
<span class="pl-k">from</span> <span class="pl-s1">pydantic</span> <span class="pl-k">import</span> <span class="pl-v">BaseModel</span>
<span class="pl-k">from</span> <span class="pl-s1">sqlalchemy</span> <span class="pl-k">import</span> <span class="pl-v">Column</span>, <span class="pl-v">ForeignKey</span>, <span class="pl-v">Integer</span>, <span class="pl-v">String</span>, <span class="pl-s1">create_engine</span>
<span class="pl-k">from</span> <span class="pl-s1">sqlalchemy</span>.<span class="pl-s1">orm</span> <span class="pl-k">import</span> <span class="pl-v">Session</span>, <span class="pl-s1">registry</span>, <span class="pl-s1">relationship</span>, <span class="pl-s1">sessionmaker</span>
<span class="pl-k">from</span> <span class="pl-s1">uvicorn</span> <span class="pl-k">import</span> <span class="pl-s1">run</span>

<span class="pl-v">SQLALCHEMY_DATABASE_URL</span> <span class="pl-c1">=</span> <span class="pl-s">"sqlite:///./sql_app.db"</span>

<span class="pl-s1">engine</span> <span class="pl-c1">=</span> <span class="pl-en">create_engine</span>(
    <span class="pl-v">SQLALCHEMY_DATABASE_URL</span>, <span class="pl-s1">connect_args</span><span class="pl-c1">=</span>{<span class="pl-s">"check_same_thread"</span>: <span class="pl-c1">False</span>}
)
<span class="pl-v">SessionLocal</span> <span class="pl-c1">=</span> <span class="pl-en">sessionmaker</span>(<span class="pl-s1">autocommit</span><span class="pl-c1">=</span><span class="pl-c1">False</span>, <span class="pl-s1">autoflush</span><span class="pl-c1">=</span><span class="pl-c1">False</span>, <span class="pl-s1">bind</span><span class="pl-c1">=</span><span class="pl-s1">engine</span>)

<span class="pl-s1">mapper</span> <span class="pl-c1">=</span> <span class="pl-en">registry</span>()


<span class="pl-en">@<span class="pl-s1">mapper</span>.<span class="pl-s1">mapped</span></span>
<span class="pl-en">@<span class="pl-s1">dataclass</span></span>
<span class="pl-k">class</span> <span class="pl-v">User</span>:
    <span class="pl-s1">__tablename__</span> <span class="pl-c1">=</span> <span class="pl-s">"users"</span>
    <span class="pl-s1">__sa_dataclass_metadata_key__</span> <span class="pl-c1">=</span> <span class="pl-s">"sa"</span>

    <span class="pl-s1">id</span>: <span class="pl-s1">int</span> <span class="pl-c1">=</span> <span class="pl-en">field</span>(
        <span class="pl-s1">metadata</span><span class="pl-c1">=</span>{
            <span class="pl-s">"sa"</span>: <span class="pl-v">Column</span>(<span class="pl-v">Integer</span>, <span class="pl-s1">primary_key</span><span class="pl-c1">=</span><span class="pl-c1">True</span>, <span class="pl-s1">index</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)
        }
    )
    <span class="pl-s1">email</span>: <span class="pl-s1">str</span> <span class="pl-c1">=</span> <span class="pl-en">field</span>(
        <span class="pl-s1">metadata</span><span class="pl-c1">=</span>{
            <span class="pl-s">"sa"</span>: <span class="pl-v">Column</span>(<span class="pl-v">String</span>, <span class="pl-s1">unique</span><span class="pl-c1">=</span><span class="pl-c1">True</span>, <span class="pl-s1">index</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)
        }
    )
    <span class="pl-s1">items</span>: <span class="pl-s1">list</span>[<span class="pl-v">Item</span>] <span class="pl-c1">=</span> <span class="pl-en">field</span>(
        <span class="pl-s1">init</span><span class="pl-c1">=</span><span class="pl-c1">False</span>,
        <span class="pl-s1">metadata</span><span class="pl-c1">=</span>{
            <span class="pl-s">"sa"</span>: <span class="pl-en">relationship</span>(<span class="pl-s">"Item"</span>, <span class="pl-s1">lazy</span><span class="pl-c1">=</span><span class="pl-s">"raise"</span>)
        }
    )

    <span class="pl-en">@<span class="pl-s1">property</span></span>
    <span class="pl-k">def</span> <span class="pl-en">greeting</span>(<span class="pl-s1">self</span>):
        <span class="pl-k">return</span> <span class="pl-s">f"Hello <span class="pl-s1"><span class="pl-kos">{</span><span class="pl-s1">self</span>.<span class="pl-s1">email</span><span class="pl-kos">}</span></span>"</span>


<span class="pl-en">@<span class="pl-s1">mapper</span>.<span class="pl-s1">mapped</span></span>
<span class="pl-en">@<span class="pl-s1">dataclass</span></span>
<span class="pl-k">class</span> <span class="pl-v">Item</span>:
    <span class="pl-s1">__tablename__</span> <span class="pl-c1">=</span> <span class="pl-s">"items"</span>
    <span class="pl-s1">__sa_dataclass_metadata_key__</span> <span class="pl-c1">=</span> <span class="pl-s">"sa"</span>

    <span class="pl-s1">id</span>: <span class="pl-s1">int</span> <span class="pl-c1">=</span> <span class="pl-en">field</span>(
        <span class="pl-s1">metadata</span><span class="pl-c1">=</span>{
            <span class="pl-s">"sa"</span>: <span class="pl-v">Column</span>(<span class="pl-v">Integer</span>, <span class="pl-s1">primary_key</span><span class="pl-c1">=</span><span class="pl-c1">True</span>, <span class="pl-s1">index</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)
        }
    )
    <span class="pl-s1">title</span>: <span class="pl-s1">str</span> <span class="pl-c1">=</span> <span class="pl-en">field</span>(
        <span class="pl-s1">metadata</span><span class="pl-c1">=</span>{
            <span class="pl-s">"sa"</span>: <span class="pl-v">Column</span>(<span class="pl-v">String</span>, <span class="pl-s1">index</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)
        }
    )
    <span class="pl-s1">owner_id</span>: <span class="pl-s1">int</span> <span class="pl-c1">=</span> <span class="pl-en">field</span>(
        <span class="pl-s1">init</span><span class="pl-c1">=</span><span class="pl-c1">False</span>,
        <span class="pl-s1">metadata</span><span class="pl-c1">=</span>{
            <span class="pl-s">"sa"</span>: <span class="pl-v">Column</span>(<span class="pl-v">Integer</span>, <span class="pl-v">ForeignKey</span>(<span class="pl-s">"users.id"</span>))
        }
    )


<span class="pl-k">class</span> <span class="pl-v">UserIn</span>(<span class="pl-v">BaseModel</span>):
    <span class="pl-s1">id</span>: <span class="pl-s1">int</span>
    <span class="pl-s1">email</span>: <span class="pl-s1">str</span>


<span class="pl-k">class</span> <span class="pl-v">UserOut</span>(<span class="pl-v">BaseModel</span>):
    <span class="pl-s1">id</span>: <span class="pl-s1">int</span>
    <span class="pl-s1">email</span>: <span class="pl-s1">str</span>
    <span class="pl-s1">greeting</span>: <span class="pl-s1">str</span>

    <span class="pl-k">class</span> <span class="pl-v">Config</span>:
        <span class="pl-s1">orm_mode</span> <span class="pl-c1">=</span> <span class="pl-c1">True</span>


<span class="pl-s1">mapper</span>.<span class="pl-s1">metadata</span>.<span class="pl-en">create_all</span>(<span class="pl-s1">bind</span><span class="pl-c1">=</span><span class="pl-s1">engine</span>)

<span class="pl-s1">app</span> <span class="pl-c1">=</span> <span class="pl-v">FastAPI</span>()


<span class="pl-k">def</span> <span class="pl-en">get_db</span>():
    <span class="pl-s1">db</span> <span class="pl-c1">=</span> <span class="pl-v">SessionLocal</span>()
    <span class="pl-k">try</span>:
        <span class="pl-k">yield</span> <span class="pl-s1">db</span>
    <span class="pl-k">finally</span>:
        <span class="pl-s1">db</span>.<span class="pl-en">close</span>()


<span class="pl-en">@<span class="pl-s1">app</span>.<span class="pl-en">post</span>(<span class="pl-s">"/users/"</span>, <span class="pl-s1">response_model</span><span class="pl-c1">=</span><span class="pl-v">UserOut</span>)</span>
<span class="pl-k">def</span> <span class="pl-en">create_user</span>(<span class="pl-s1">user</span>: <span class="pl-v">UserIn</span>, <span class="pl-s1">db</span>: <span class="pl-v">Session</span> <span class="pl-c1">=</span> <span class="pl-v">Depends</span>(<span class="pl-s1">get_db</span>)):
    <span class="pl-s1">instance</span> <span class="pl-c1">=</span> <span class="pl-v">User</span>(
        <span class="pl-s1">id</span><span class="pl-c1">=</span><span class="pl-s1">user</span>.<span class="pl-s1">id</span>,
        <span class="pl-s1">email</span><span class="pl-c1">=</span><span class="pl-s1">user</span>.<span class="pl-s1">email</span>
    )
    <span class="pl-s1">db</span>.<span class="pl-en">add</span>(<span class="pl-s1">instance</span>)
    <span class="pl-s1">db</span>.<span class="pl-en">commit</span>()
    <span class="pl-k">return</span> <span class="pl-s1">instance</span>


<span class="pl-k">if</span> <span class="pl-s1">__name__</span> <span class="pl-c1">==</span> <span class="pl-s">'__main__'</span>:
    <span class="pl-en">run</span>(<span class="pl-s1">app</span>)</pre></div>
<h3 dir="auto">Description</h3>
<p dir="auto">Example code works if <code class="notranslate">fastapi==0.66.1</code> and it does not work if <code class="notranslate">fastapi==0.67.0</code>.<br>
Open a browser, hit <code class="notranslate">POST /users/</code> endpoint and create a user</p>
<p dir="auto">Expected behaviour: User is created and displayed successfully.<br>
Current behavior: User is created successfully (check in DB), but is not displayed successfully due to serialization errors.</p>
<p dir="auto">Most likely the reason is in the new dataclass related features of FastAPI 0.67.0. Since the new-style database models are dataclasses as well, therefore they are affected too. As far as I can see if an instance is the dataclass, then FastAPI makes a <code class="notranslate">dict</code> (<code class="notranslate">dataclasses.asdict(res)</code>) out of instance before doing serialization.<br>
It has two issues: first, if a dataclass has a property, it won't be serialized; second, if a dataclass has a relationship with <code class="notranslate">lazy="raise"</code> (means we should load this relationship explicitly), it is actually accessed and caused SQLAlchemy's exception.<br>
Technically, if we let <code class="notranslate">pydantic</code> to serialize this dataclass, we won't get any of those issues. I assume it was the case for previous versions of FastAPI.</p>
<p dir="auto">Here are a few links:<br>
<a href="https://docs.sqlalchemy.org/en/14/orm/mapping_styles.html#orm-declarative-dataclasses-declarative-table" rel="nofollow">https://docs.sqlalchemy.org/en/14/orm/mapping_styles.html#orm-declarative-dataclasses-declarative-table</a><br>
<a href="https://docs.sqlalchemy.org/en/14/orm/loading_relationships.html#prevent-lazy-with-raiseload" rel="nofollow">https://docs.sqlalchemy.org/en/14/orm/loading_relationships.html#prevent-lazy-with-raiseload</a></p>
<h3 dir="auto">Operating System</h3>
<p dir="auto">Windows</p>
<h3 dir="auto">Operating System Details</h3>
<p dir="auto"><em>No response</em></p>
<h3 dir="auto">FastAPI Version</h3>
<p dir="auto">0.67.0</p>
<h3 dir="auto">Python Version</h3>
<p dir="auto">3.9.6</p>
<h3 dir="auto">Additional Context</h3>
<p dir="auto"><em>No response</em></p>
<p dir="auto"><a href="https://github.com/tortoise/tortoise-orm">https://github.com/tortoise/tortoise-orm</a></p>