title: Is there a way to return two fields from SQLAlchemy / FastAPI relationship?
body: <p>structure</p>
  <pre><code>.
  └── sql_app
      ├── __init__.py
      ├── crud.py
      ├── database.py
      ├── main.py
      ├── models.py
      └── schemas.py
  </code></pre>
  <p>main.py</p>
  <pre><code>from typing import List
  
  from fastapi import Depends, FastAPI, HTTPException
  from sqlalchemy.orm import Session
  
  from . import crud, models, schemas
  from .database import SessionLocal, engine
  
  models.Base.metadata.create_all(bind=engine)
  
  app = FastAPI()
  
  
  # Dependency
  def get_db():
      db = SessionLocal()
      try:
          yield db
      finally:
          db.close()
  
  
  @app.post(&quot;/users/&quot;, response_model=schemas.User)
  def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)):
      db_user = crud.get_user_by_name(db, name=user.name)
      if db_user:
          raise HTTPException(status_code=400, detail=&quot;Name already registered&quot;)
      return crud.create_user(db=db, user=user)
  
  
  @app.get(&quot;/users/&quot;, response_model=List[schemas.User])
  def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
      users = crud.get_users(db, skip=skip, limit=limit)
      return users
  
  
  @app.get(&quot;/users/{user_id}&quot;, response_model=schemas.User)
  def read_user(user_id: int, db: Session = Depends(get_db)):
      db_user = crud.get_user(db, user_id=user_id)
      if db_user is None:
          raise HTTPException(status_code=404, detail=&quot;User not found&quot;)
      return db_user
  
  
  @app.post(&quot;/users/{user_id}/messages/&quot;, response_model=schemas.Message)
  def create_message_for_user(
      user_id: int, message: schemas.MessageCreate, db: Session = Depends(get_db)
  ):
      return crud.create_user_message(db=db, message=message, user_id=user_id)
  
  
  @app.get(&quot;/messages/&quot;, response_model=List[schemas.MessageWithUser])
  def read_messages(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
      messages = crud.get_messages(db, skip=skip, limit=limit)
      return messages
  </code></pre>
  <p>crud.py</p>
  <pre><code>from sqlalchemy.orm import Session
  
  from . import models, schemas
  
  
  def get_user(db: Session, user_id: int):
      return db.query(models.User).filter(models.User.id == user_id).first()
  
  
  def get_user_by_name(db: Session, name: str):
      return db.query(models.User).filter(models.User.name == name).first()
  
  
  def get_users(db: Session, skip: int = 0, limit: int = 100):
      return db.query(models.User).offset(skip).limit(limit).all()
  
  
  def create_user(db: Session, user: schemas.UserCreate):
      db_user = models.User(name=user.name)
      db.add(db_user)
      db.commit()
      db.refresh(db_user)
      return db_user
  
  
  def get_messages(db: Session, skip: int = 0, limit: int = 100):
      return db.query(models.Message).offset(skip).limit(limit).all()
  
  
  def create_user_message(db: Session, message: schemas.MessageCreate, user_id: int):
      db_item = models.Message(**message.dict(), user_id=user_id)
      db.add(db_item)
      db.commit()
  db.refresh(db_item)
  return db_item
  </code></pre>
  <p>database.py</p>
  <pre><code>from sqlalchemy import create_engine
  from sqlalchemy.ext.declarative import declarative_base
  from sqlalchemy.orm import sessionmaker
  
  SQLALCHEMY_DATABASE_URL = &quot;sqlite:///./sql_app.db&quot;
  # SQLALCHEMY_DATABASE_URL = &quot;postgresql://user:password@postgresserver/db&quot;
  
  engine = create_engine(
      SQLALCHEMY_DATABASE_URL, connect_args={&quot;check_same_thread&quot;: False}
  )
  SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
  
  Base = declarative_base()
  </code></pre>
  <p>models.py</p>
  <pre><code>from sqlalchemy import Boolean, Column, ForeignKey, Integer, String
  from sqlalchemy.orm import relationship
  
  from .database import Base
  
  
  class User(Base):
      __tablename__ = &quot;users&quot;
  
      id = Column(Integer, primary_key=True, index=True)
      name = Column(String, index=True, unique=True, nullable=False)
  
      messages = relationship(&quot;Message&quot;, back_populates=&quot;user&quot;)
  
  
  class Message(Base):
      __tablename__ = &quot;messages&quot;
  
      id = Column(Integer, primary_key=True, index=True)
      title = Column(String, index=True, unique=True, nullable=False)
      message = Column(String, index=False)
      user_id = Column(Integer, ForeignKey(&quot;users.id&quot;))
  
      user = relationship(&quot;User&quot;, back_populates=&quot;messages&quot;)
  </code></pre>
  <p>schemas.py</p>
  <pre><code>from typing import List
  
  from pydantic import BaseModel
  
  
  class MessageBase(BaseModel):
      title: str
      message: str
  
  
  class MessageCreate(MessageBase):
      pass
  
  
  class Message(MessageBase):
      id: int
      user_id: int
  
      class Config:
          orm_mode = True
  
  
  class UserBase(BaseModel):
      name: str
  
  
  class UserCreate(UserBase):
      pass
  
  
  class User(UserBase):
      id: int
      messages: List[Message] = []
  
      class Config:
          orm_mode = True
  
  
  class UserIdentifier(UserBase):
      id: int
      name: str
  
  
  class MessageWithUser(MessageBase):
      id: int
      title: str
      message: str
      user: UserIdentifier
  </code></pre>
  <p>Run cmd:</p>
  <pre><code>uvicorn sql_app.main:app --reload
  </code></pre>
  <p>Navigate to: 127.0.0.1:8000/docs</p>
  <p>Add users and messages for users</p>
  <p>Try to read messages</p>
  <p>The example result is the correct format but it does not give a response just 500 error and the following</p>
  <p>Error:</p>
  <pre><code>pydantic.error_wrappers.ValidationError: 4 validation errors for MessageWithUser
  response -&gt; 0
    value is not a valid dict (type=type_error.dict)
  response -&gt; 1
    value is not a valid dict (type=type_error.dict)
  response -&gt; 2
    value is not a valid dict (type=type_error.dict)
  response -&gt; 3
    value is not a valid dict (type=type_error.dict)
  </code></pre>
  <p>The expected output is what is shown in the example output of the docs page, with UserIdentifier being added to Message but not any other fields from User if there were any, in this case there is not</p>