title: FastAPI: Data rows from Postgresql Database don't map to Pydantic schema
body: <p>I'm using the FastAPI framework with Asyncio.  I have recently switched to Postgresql from MySQL and have swapped <code>aiomysql</code> for <code>asyncpg</code> accordingly.</p>
  <p>In MySQL I could fetch this from Database and it would be cast into Pydantic schema automatically.</p>
  <pre><code>async def get_device(device_id: str) -&gt; Device:
      query = DeviceTable.select().where(DeviceTable.c.id == device_id)
      return await db.fetch_one(query)
  </code></pre>
  <p><strong>Pydantic schema:</strong></p>
  <pre><code>class Device(BaseModel):
      id: str
      type: DeviceType
      created_at: datetime
      last_login_at: datetime
      is_banned: bool
      ...
  </code></pre>
  <p>However when using Postgres this conversion doesn't seem to happen anymore.</p>
  <pre><code>device: Device = await crud_device.get_device(body.device_id)
  </code></pre>
  <p>For <code>device.is_banned</code> I get the error message <code>{AttributeError}'Record' object has no attribute 'is_banned'</code>.</p>
  <p>The device object is in this case a Record object <code>&lt;databases.backends.postgres.Record object at 0x10d2c9860&gt;</code> instead of Pydantic Schema.</p>
  <p>I still can access the values like this:</p>
  <p><code>device['is_banned']</code></p>
  <p>Why would FastAPI's behaviour change only because I picked a different database? I can't find anything in the documentation about this.</p>
  <p><strong>UPDATE</strong></p>
  <p>Model:</p>
  <pre><code>DeviceTable = sqlalchemy.Table(
      &quot;device&quot;,
      metadata,
      Column(&quot;id&quot;, String(36), primary_key=True),
      Column(&quot;type&quot;, Enum(DeviceType), nullable=False),
      Column(
          &quot;created_at&quot;,
          TIMESTAMP(),
          nullable=False,
          default=func.now(),
          server_default=func.now(),
      ),
      Column(&quot;last_login_at&quot;, TIMESTAMP(), nullable=True),
      Column(&quot;expires_at&quot;, TIMESTAMP()),
      Column(&quot;account_type&quot;, Enum(AccountType), nullable=False),
      Column(&quot;strikes&quot;, Integer(), nullable=True),
      Column(
          &quot;is_banned&quot;,
          Boolean(),
          nullable=False,
          server_default=sql.false(),
          default=sql.false(),
      ),
      Column(&quot;account_id&quot;, ForeignKey(&quot;account.id&quot;), nullable=True, index=True),
  )
  </code></pre>
  <p>I seem to have found a workaround. I have to cast the record explicitly into the Pydantic schema.</p>
  <pre><code>async def get_device(device_id: str) -&gt; Device:
      query = DeviceTable.select().where(DeviceTable.c.id == device_id)
      record = await db.fetch_one(query)
      return Device(**record)
  </code></pre>
  <p>This is quite odd that it doesn't happen automatically. I have to change code because the underlying database has changed. The worse part is that when no record has been found, the cast will crash. Hence I have to make more repetitive changes:</p>
  <pre><code>async def get_device(device_id: str) -&gt; Optional[Device]:
      query = DeviceTable.select().where(DeviceTable.c.id == device_id)
      record = await db.fetch_one(query)
      if record:
          return Device(**record)
      else:
          return None
  </code></pre>