Files

619 lines
31 KiB
HTML

<!DOCTYPE html>
<html class="no-js" lang="en">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width,initial-scale=1" name="viewport"/>
<meta content="Ready-to-use and customizable users management for FastAPI" name="description"/>
<link href="../../../favicon.png" rel="icon"/>
<meta content="mkdocs-1.2.2, mkdocs-material-7.2.7" name="generator"/>
<title>SQLAlchemy - FastAPI Users</title>
<link href="../../../assets/stylesheets/main.3c7cdd75.min.css" rel="stylesheet"/>
<link href="../../../assets/stylesheets/palette.3f5d1f46.min.css" rel="stylesheet"/>
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700%7CRoboto+Mono&amp;display=fallback" rel="stylesheet"/>
<style>:root{--md-text-font-family:"Roboto";--md-code-font-family:"Roboto Mono"}</style>
</head>
<body data-md-color-accent="red" data-md-color-primary="red" data-md-color-scheme="default" dir="ltr">
<script>function __prefix(e){return new URL("../../..",location).pathname+"."+e}function __get(e,t=localStorage){return JSON.parse(t.getItem(__prefix(e)))}</script>
<script>var palette=__get("__palette");if(null!==palette&&"object"==typeof palette.color)for(var key in palette.color)document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a class="md-skip" href="#sqlalchemy">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header" data-md-component="header">
<nav aria-label="Header" class="md-header__inner md-grid">
<a aria-label="FastAPI Users" class="md-header__button md-logo" data-md-component="logo" href="../../.." title="FastAPI Users">
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M16.5 12A2.5 2.5 0 0 0 19 9.5 2.5 2.5 0 0 0 16.5 7 2.5 2.5 0 0 0 14 9.5a2.5 2.5 0 0 0 2.5 2.5M9 11a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m7.5 3c-1.83 0-5.5.92-5.5 2.75V19h11v-2.25c0-1.83-3.67-2.75-5.5-2.75M9 13c-2.33 0-7 1.17-7 3.5V19h7v-2.25c0-.85.33-2.34 2.37-3.47C10.5 13.1 9.66 13 9 13z"></path></svg>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2z"></path></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
FastAPI Users
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
SQLAlchemy
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input aria-label="Switch to dark mode" class="md-option" data-md-color-accent="red" data-md-color-media="" data-md-color-primary="red" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
<label class="md-header__button md-icon" for="__palette_2" hidden="" title="Switch to dark mode">
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2a7 7 0 0 0-7 7c0 2.38 1.19 4.47 3 5.74V17a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1v-2.26c1.81-1.27 3-3.36 3-5.74a7 7 0 0 0-7-7M9 21a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1v-1H9v1z"></path></svg>
</label>
<input aria-label="Switch to light mode" class="md-option" data-md-color-accent="red" data-md-color-media="" data-md-color-primary="red" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
<label class="md-header__button md-icon" for="__palette_1" hidden="" title="Switch to light mode">
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2a7 7 0 0 1 7 7c0 2.38-1.19 4.47-3 5.74V17a1 1 0 0 1-1 1H9a1 1 0 0 1-1-1v-2.26C6.19 13.47 5 11.38 5 9a7 7 0 0 1 7-7M9 21v-1h6v1a1 1 0 0 1-1 1h-4a1 1 0 0 1-1-1m3-17a5 5 0 0 0-5 5c0 2.05 1.23 3.81 3 4.58V16h4v-2.42c1.77-.77 3-2.53 3-4.58a5 5 0 0 0-5-5z"></path></svg>
</label>
</form>
<label class="md-header__button md-icon" for="__search">
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"></path></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input aria-label="Search" autocapitalize="off" autocomplete="off" autocorrect="off" class="md-search__input" data-md-component="search-query" name="query" placeholder="Search" required="" spellcheck="false" type="text"/>
<label class="md-search__icon md-icon" for="__search">
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"></path></svg>
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"></path></svg>
</label>
<nav aria-label="Search" class="md-search__options">
<button aria-label="Clear" class="md-search__icon md-icon" tabindex="-1" type="reset">
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"></path></svg>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix="">
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a class="md-source" data-md-component="source" href="https://github.com/fastapi-users/fastapi-users" title="Go to repository">
<div class="md-source__icon md-icon">
<svg viewbox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"></path></svg>
</div>
<div class="md-source__repository">
frankie567/fastapi-users
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a aria-label="FastAPI Users" class="md-nav__button md-logo" data-md-component="logo" href="../../.." title="FastAPI Users">
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M16.5 12A2.5 2.5 0 0 0 19 9.5 2.5 2.5 0 0 0 16.5 7 2.5 2.5 0 0 0 14 9.5a2.5 2.5 0 0 0 2.5 2.5M9 11a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m7.5 3c-1.83 0-5.5.92-5.5 2.75V19h11v-2.25c0-1.83-3.67-2.75-5.5-2.75M9 13c-2.33 0-7 1.17-7 3.5V19h7v-2.25c0-.85.33-2.34 2.37-3.47C10.5 13.1 9.66 13 9 13z"></path></svg>
</a>
FastAPI Users
</label>
<div class="md-nav__source">
<a class="md-source" data-md-component="source" href="https://github.com/fastapi-users/fastapi-users" title="Go to repository">
<div class="md-source__icon md-icon">
<svg viewbox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"></path></svg>
</div>
<div class="md-source__repository">
frankie567/fastapi-users
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a class="md-nav__link" href="../../..">
About
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../../installation/">
Installation
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_3" id="__nav_3" type="checkbox"/>
<label class="md-nav__link" for="__nav_3">
Configuration
<span class="md-nav__icon md-icon"></span>
</label>
<nav aria-label="Configuration" class="md-nav" data-md-level="1">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a class="md-nav__link" href="../../overview/">
Overview
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../models/">
Models
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_3_3" id="__nav_3_3" type="checkbox"/>
<label class="md-nav__link" for="__nav_3_3">
Database adapters
<span class="md-nav__icon md-icon"></span>
</label>
<nav aria-label="Database adapters" class="md-nav" data-md-level="2">
<label class="md-nav__title" for="__nav_3_3">
<span class="md-nav__icon md-icon"></span>
Database adapters
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
<label class="md-nav__link md-nav__link--active" for="__toc">
SQLAlchemy
<span class="md-nav__icon md-icon"></span>
</label>
<a class="md-nav__link md-nav__link--active" href="./">
SQLAlchemy
</a>
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix="">
<li class="md-nav__item">
<a class="md-nav__link" href="#installation">
Installation
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="#setup-user-table">
Setup User table
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="#create-the-tables">
Create the tables
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="#create-the-database-adapter-dependency">
Create the database adapter dependency
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="#what-about-sqlalchemy-orm">
What about SQLAlchemy ORM?
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../mongodb/">
MongoDB
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../tortoise/">
Tortoise ORM
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../ormar/">
Ormar
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_3_4" id="__nav_3_4" type="checkbox"/>
<label class="md-nav__link" for="__nav_3_4">
Authentication backends
<span class="md-nav__icon md-icon"></span>
</label>
<nav aria-label="Authentication backends" class="md-nav" data-md-level="2">
<label class="md-nav__title" for="__nav_3_4">
<span class="md-nav__icon md-icon"></span>
Authentication backends
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a class="md-nav__link" href="../../authentication/">
Introduction
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../authentication/jwt/">
JWT
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../authentication/cookie/">
Cookie
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../user-manager/">
UserManager
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_3_6" id="__nav_3_6" type="checkbox"/>
<label class="md-nav__link" for="__nav_3_6">
Routers
<span class="md-nav__icon md-icon"></span>
</label>
<nav aria-label="Routers" class="md-nav" data-md-level="2">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Routers
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a class="md-nav__link" href="../../routers/">
Introduction
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../routers/auth/">
Auth router
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../routers/register/">
Register routes
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../routers/verify/">
Verify router
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../routers/reset/">
Reset password router
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../routers/users/">
Users router
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../full-example/">
Full example
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../oauth/">
OAuth2
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
<label class="md-nav__link" for="__nav_4">
Usage
<span class="md-nav__icon md-icon"></span>
</label>
<nav aria-label="Usage" class="md-nav" data-md-level="1">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
Usage
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a class="md-nav__link" href="../../../usage/flow/">
Flow
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../../usage/routes/">
Routes
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../../usage/current-user/">
Get current user
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5" id="__nav_5" type="checkbox"/>
<label class="md-nav__link" for="__nav_5">
Migration
<span class="md-nav__icon md-icon"></span>
</label>
<nav aria-label="Migration" class="md-nav" data-md-level="1">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Migration
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a class="md-nav__link" href="../../../migration/08_to_1x/">
0.8.x ➡️ 1.x.x
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../../migration/1x_to_2x/">
1.x.x ➡️ 2.x.x
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../../migration/2x_to_3x/">
2.x.x ➡️ 3.x.x
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../../migration/3x_to_4x/">
3.x.x ➡️ 4.x.x
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../../migration/4x_to_5x/">
4.x.x ➡️ 5.x.x
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../../migration/6x_to_7x/">
6.x.x ➡️ 7.x.x
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="../../../migration/7x_to_8x/">
7.x.x ➡️ 8.x.x
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix="">
<li class="md-nav__item">
<a class="md-nav__link" href="#installation">
Installation
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="#setup-user-table">
Setup User table
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="#create-the-tables">
Create the tables
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="#create-the-database-adapter-dependency">
Create the database adapter dependency
</a>
</li>
<li class="md-nav__item">
<a class="md-nav__link" href="#what-about-sqlalchemy-orm">
What about SQLAlchemy ORM?
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="sqlalchemy">SQLAlchemy<a class="headerlink" href="#sqlalchemy" title="Permanent link"></a></h1>
<p><strong>FastAPI Users</strong> provides the necessary tools to work with SQL databases thanks to <a href="https://docs.sqlalchemy.org/en/13/core/">SQLAlchemy Core</a> and <a href="https://www.encode.io/databases/">encode/databases</a> package for full async support.</p>
<h2 id="installation">Installation<a class="headerlink" href="#installation" title="Permanent link"></a></h2>
<p>Install the database driver that corresponds to your DBMS:</p>
<div class="highlight"><pre><span></span><code>pip install <span class="s1">'databases[postgresql]'</span>
</code></pre></div>
<div class="highlight"><pre><span></span><code>pip install <span class="s1">'databases[mysql]'</span>
</code></pre></div>
<div class="highlight"><pre><span></span><code>pip install <span class="s1">'databases[sqlite]'</span>
</code></pre></div>
<p>For the sake of this tutorial from now on, we'll use a simple SQLite databse.</p>
<h2 id="setup-user-table">Setup User table<a class="headerlink" href="#setup-user-table" title="Permanent link"></a></h2>
<p>Let's declare our SQLAlchemy <code>User</code> table.</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">databases</span>
<span class="kn">import</span> <span class="nn">sqlalchemy</span>
<span class="kn">from</span> <span class="nn">fastapi_users.db</span> <span class="kn">import</span> <span class="n">SQLAlchemyBaseUserTable</span><span class="p">,</span> <span class="n">SQLAlchemyUserDatabase</span>
<span class="kn">from</span> <span class="nn">sqlalchemy.ext.declarative</span> <span class="kn">import</span> <span class="n">DeclarativeMeta</span><span class="p">,</span> <span class="n">declarative_base</span>
<span class="kn">from</span> <span class="nn">.models</span> <span class="kn">import</span> <span class="n">UserDB</span>
<span class="n">DATABASE_URL</span> <span class="o">=</span> <span class="s2">"sqlite:///./test.db"</span>
<span class="n">database</span> <span class="o">=</span> <span class="n">databases</span><span class="o">.</span><span class="n">Database</span><span class="p">(</span><span class="n">DATABASE_URL</span><span class="p">)</span>
<span class="n">Base</span><span class="p">:</span> <span class="n">DeclarativeMeta</span> <span class="o">=</span> <span class="n">declarative_base</span><span class="p">()</span>
<span class="hll"><span class="k">class</span> <span class="nc">UserTable</span><span class="p">(</span><span class="n">Base</span><span class="p">,</span> <span class="n">SQLAlchemyBaseUserTable</span><span class="p">):</span>
</span><span class="hll"> <span class="k">pass</span>
</span>
<span class="n">engine</span> <span class="o">=</span> <span class="n">sqlalchemy</span><span class="o">.</span><span class="n">create_engine</span><span class="p">(</span>
<span class="n">DATABASE_URL</span><span class="p">,</span> <span class="n">connect_args</span><span class="o">=</span><span class="p">{</span><span class="s2">"check_same_thread"</span><span class="p">:</span> <span class="kc">False</span><span class="p">}</span>
<span class="p">)</span>
<span class="n">Base</span><span class="o">.</span><span class="n">metadata</span><span class="o">.</span><span class="n">create_all</span><span class="p">(</span><span class="n">engine</span><span class="p">)</span>
<span class="n">users</span> <span class="o">=</span> <span class="n">UserTable</span><span class="o">.</span><span class="n">__table__</span>
<span class="k">def</span> <span class="nf">get_user_db</span><span class="p">():</span>
<span class="k">yield</span> <span class="n">SQLAlchemyUserDatabase</span><span class="p">(</span><span class="n">UserDB</span><span class="p">,</span> <span class="n">database</span><span class="p">,</span> <span class="n">users</span><span class="p">)</span>
</code></pre></div>
<p>As you can see, <strong>FastAPI Users</strong> provides a mixin that will include base fields for our <code>User</code> table. You can of course add you own fields there to fit to your needs!</p>
<h2 id="create-the-tables">Create the tables<a class="headerlink" href="#create-the-tables" title="Permanent link"></a></h2>
<p>We'll now create an SQLAlchemy engine and ask it to create all the defined tables.</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">databases</span>
<span class="kn">import</span> <span class="nn">sqlalchemy</span>
<span class="kn">from</span> <span class="nn">fastapi_users.db</span> <span class="kn">import</span> <span class="n">SQLAlchemyBaseUserTable</span><span class="p">,</span> <span class="n">SQLAlchemyUserDatabase</span>
<span class="kn">from</span> <span class="nn">sqlalchemy.ext.declarative</span> <span class="kn">import</span> <span class="n">DeclarativeMeta</span><span class="p">,</span> <span class="n">declarative_base</span>
<span class="kn">from</span> <span class="nn">.models</span> <span class="kn">import</span> <span class="n">UserDB</span>
<span class="n">DATABASE_URL</span> <span class="o">=</span> <span class="s2">"sqlite:///./test.db"</span>
<span class="n">database</span> <span class="o">=</span> <span class="n">databases</span><span class="o">.</span><span class="n">Database</span><span class="p">(</span><span class="n">DATABASE_URL</span><span class="p">)</span>
<span class="n">Base</span><span class="p">:</span> <span class="n">DeclarativeMeta</span> <span class="o">=</span> <span class="n">declarative_base</span><span class="p">()</span>
<span class="k">class</span> <span class="nc">UserTable</span><span class="p">(</span><span class="n">Base</span><span class="p">,</span> <span class="n">SQLAlchemyBaseUserTable</span><span class="p">):</span>
<span class="k">pass</span>
<span class="hll"><span class="n">engine</span> <span class="o">=</span> <span class="n">sqlalchemy</span><span class="o">.</span><span class="n">create_engine</span><span class="p">(</span>
</span><span class="hll"> <span class="n">DATABASE_URL</span><span class="p">,</span> <span class="n">connect_args</span><span class="o">=</span><span class="p">{</span><span class="s2">"check_same_thread"</span><span class="p">:</span> <span class="kc">False</span><span class="p">}</span>
</span><span class="hll"><span class="p">)</span>
</span><span class="hll"><span class="n">Base</span><span class="o">.</span><span class="n">metadata</span><span class="o">.</span><span class="n">create_all</span><span class="p">(</span><span class="n">engine</span><span class="p">)</span>
</span>
<span class="n">users</span> <span class="o">=</span> <span class="n">UserTable</span><span class="o">.</span><span class="n">__table__</span>
<span class="k">def</span> <span class="nf">get_user_db</span><span class="p">():</span>
<span class="k">yield</span> <span class="n">SQLAlchemyUserDatabase</span><span class="p">(</span><span class="n">UserDB</span><span class="p">,</span> <span class="n">database</span><span class="p">,</span> <span class="n">users</span><span class="p">)</span>
</code></pre></div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>In production, it's strongly recommended to setup a migration system to update your SQL schemas. See <a href="https://alembic.sqlalchemy.org/en/latest/">Alembic</a>.</p>
</div>
<h2 id="create-the-database-adapter-dependency">Create the database adapter dependency<a class="headerlink" href="#create-the-database-adapter-dependency" title="Permanent link"></a></h2>
<p>The database adapter of <strong>FastAPI Users</strong> makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency.</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">databases</span>
<span class="kn">import</span> <span class="nn">sqlalchemy</span>
<span class="kn">from</span> <span class="nn">fastapi_users.db</span> <span class="kn">import</span> <span class="n">SQLAlchemyBaseUserTable</span><span class="p">,</span> <span class="n">SQLAlchemyUserDatabase</span>
<span class="kn">from</span> <span class="nn">sqlalchemy.ext.declarative</span> <span class="kn">import</span> <span class="n">DeclarativeMeta</span><span class="p">,</span> <span class="n">declarative_base</span>
<span class="kn">from</span> <span class="nn">.models</span> <span class="kn">import</span> <span class="n">UserDB</span>
<span class="n">DATABASE_URL</span> <span class="o">=</span> <span class="s2">"sqlite:///./test.db"</span>
<span class="n">database</span> <span class="o">=</span> <span class="n">databases</span><span class="o">.</span><span class="n">Database</span><span class="p">(</span><span class="n">DATABASE_URL</span><span class="p">)</span>
<span class="n">Base</span><span class="p">:</span> <span class="n">DeclarativeMeta</span> <span class="o">=</span> <span class="n">declarative_base</span><span class="p">()</span>
<span class="k">class</span> <span class="nc">UserTable</span><span class="p">(</span><span class="n">Base</span><span class="p">,</span> <span class="n">SQLAlchemyBaseUserTable</span><span class="p">):</span>
<span class="k">pass</span>
<span class="n">engine</span> <span class="o">=</span> <span class="n">sqlalchemy</span><span class="o">.</span><span class="n">create_engine</span><span class="p">(</span>
<span class="n">DATABASE_URL</span><span class="p">,</span> <span class="n">connect_args</span><span class="o">=</span><span class="p">{</span><span class="s2">"check_same_thread"</span><span class="p">:</span> <span class="kc">False</span><span class="p">}</span>
<span class="p">)</span>
<span class="n">Base</span><span class="o">.</span><span class="n">metadata</span><span class="o">.</span><span class="n">create_all</span><span class="p">(</span><span class="n">engine</span><span class="p">)</span>
<span class="n">users</span> <span class="o">=</span> <span class="n">UserTable</span><span class="o">.</span><span class="n">__table__</span>
<span class="hll"><span class="k">def</span> <span class="nf">get_user_db</span><span class="p">():</span>
</span><span class="hll"> <span class="k">yield</span> <span class="n">SQLAlchemyUserDatabase</span><span class="p">(</span><span class="n">UserDB</span><span class="p">,</span> <span class="n">database</span><span class="p">,</span> <span class="n">users</span><span class="p">)</span>
</span></code></pre></div>
<p>Notice that we pass it three things:</p>
<ul>
<li>A reference to your <a href="../../models/"><code>UserDB</code> model</a>.</li>
<li>A <code>database</code> instance, which allows us to do asynchronous request to the database.</li>
<li>The <code>users</code> variable, which is the actual SQLAlchemy table behind the table class.</li>
</ul>
<h2 id="what-about-sqlalchemy-orm">What about SQLAlchemy ORM?<a class="headerlink" href="#what-about-sqlalchemy-orm" title="Permanent link"></a></h2>
<p>The primary objective was to use pure async approach as much as possible. However, we understand that ORM is convenient and useful for many developers. If this feature becomes very demanded, we will add a database adapter for SQLAlchemy ORM.</p>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<nav aria-label="Footer" class="md-footer__inner md-grid">
<a aria-label="Previous: Models" class="md-footer__link md-footer__link--prev" href="../../models/" rel="prev">
<div class="md-footer__button md-icon">
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"></path></svg>
</div>
<div class="md-footer__title">
<div class="md-ellipsis">
<span class="md-footer__direction">
Previous
</span>
Models
</div>
</div>
</a>
<a aria-label="Next: MongoDB" class="md-footer__link md-footer__link--next" href="../mongodb/" rel="next">
<div class="md-footer__title">
<div class="md-ellipsis">
<span class="md-footer__direction">
Next
</span>
MongoDB
</div>
</div>
<div class="md-footer__button md-icon">
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4z"></path></svg>
</div>
</a>
</nav>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "../../..", "features": [], "translations": {"clipboard.copy": "Copy to clipboard", "clipboard.copied": "Copied to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.placeholder": "Type to start searching", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.term.missing": "Missing", "select.version.title": "Select version"}, "search": "../../../assets/javascripts/workers/search.94ec81fe.min.js", "version": null}</script>
<script src="../../../assets/javascripts/bundle.48dfec6c.min.js"></script>
<script src="https://unpkg.com/mermaid/dist/mermaid.min.js"></script>
</body>
</html>