Intro
Einführung von FastAPI + TypeScript + OpenAPI als Technologie-Stack zum schnellen Erstellen von Webanwendungen mit maschinellem Lernen und Bildverarbeitung als Back-End in Python. Motivation - Ich möchte mit Python schnell einen Webserver (API-Server) einrichten - Verwenden Sie wie früher Flask - "Mit Python" ――Weil es sich um einen maschinellen Lern- / Bildverarbeitungsdienst handelt ―― "Knusprig" ――Ich möchte die Validierung genießen
width
or w
FastAPI? https://fastapi.tiangolo.com/
Demo
Von den oben genannten Motivationen
―― Richten Sie schnell eine API ein
Demo davon
Klicken Sie hier für ein Beispiel-Repository: https://github.com/tuttieee/fastapi-typescript-openapi-example
Fahren Sie grundsätzlich gemäß dem Fast API-Tutorial fort, das jedoch für ↑ leicht geändert wurde.
Gemäß https://fastapi.tiangolo.com/deployment/.
/ backend
einfügen, um es zu einem Monorepo mit Frontend zu machen.
――Um später Migration usw. hinzuzufügen, graben Sie eine weitere Ebene und machen Sie sie zu "/ backend / app / app". / backend / app
ist auf dem Docker-Container montiertVersuchen Sie nach docker-compose build
, docker-compose up
curl localhost: 8000
$ curl localhost:8000
{"Hello":"World"}
Beispiel: https://github.com/tuttieee/fastapi-typescript-openapi-example/commit/703af24fff8d39e261e1f1ce5ba859f28e806fb2
docker-compose.devel.yml
--Mounten Sie das Host-Verzeichnis/ start-reload.sh
als Befehl von Docker Run an, um das automatische Neuladen zu aktivieren (Official Docker Image. gunicorn-fastapi /) Option)Beispiel: https://github.com/tuttieee/fastapi-typescript-openapi-example/commit/33f6e91bc48c9c6396a9ceaf1e720b88c78a6822
Grundsätzlich nach ↓ vorgehen. Der Teil, der MySQL verwendet, wird unabhängig hinzugefügt.
https://fastapi.tiangolo.com/tutorial/sql-databases/
Verwenden Sie vorerst direkt die Docker-Datei, um "pip install sqlalchemy" auszuführen
Beispiel: https://github.com/tuttieee/fastapi-typescript-openapi-example/commit/75b7d2d7ccb8bc5a142b86bd3800b5e190732628
--Erstellen Sie "app / app / __ init __. Py", "app / app / database.py", "app / app / models.py"
from app import models
from app.database import SessionLocal, engine
models.Base.metadata.create_all(bind=engine)
user = models.User(email='[email protected]', hashed_password='')
db = SessionLocal()
db.add(user)
db.commit()
db.close()
db = SessionLocal()
db.query(models.User).all()
Beispiel: https://github.com/tuttieee/fastapi-typescript-openapi-example/commit/8f0d85445c33bfddd05466060b11501c2f3748b3
MySQL
RUN apt-get update && apt-get install -y \
default-mysql-client \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN pip install sqlalchemy PyMySQL
Stichprobe:
-Verwenden Sie Offizielles Bild. Grundsätzlich schreiben Sie die Einstellungen in "docker-compose.yml" gemäß README
Beispiel: https://github.com/tuttieee/fastapi-typescript-openapi-example/commit/22d760d963394f340622ea402fdcf72f02cd240f
Alembic
pip install alembic
zu Dockerfile
hinzugefügt (wird es in die Datei resources.txt konvertiert?) -> Docker-compose build
--Update database.py
create_engine
für MySQL (entferne unnötige Argumente)Tipps: Sie können die Starlette-Klasse unverändert verwenden
Betreten Sie dann die Shell und gehen Sie wie folgt vor:
alembic init migrations
Ref: https://alembic.sqlalchemy.org/en/latest/tutorial.htmlBeispiel: https://github.com/tuttieee/fastapi-typescript-openapi-example/commit/979f4b3982b3ce3e7631661af3171000d6ea0381
Ref: https://alembic.sqlalchemy.org/en/latest/autogenerate.html
alembic.ini
sqlalchemy.url
(weil es aus database.py
stammt)migrations / env.py
-Added ↓from app.models import Base
from app.database import SQLALCHEMY_DATABASE_URL
config.set_main_option("sqlalchemy.url", SQLALCHEMY_DATABASE_URL)
target_metadata = Base.metadata
models.py
für MySQL (geben Sie die Länge in String
an)alembic revision --autogenerate -m "Add users and items tables"
Beispiel: https://github.com/tuttieee/fastapi-typescript-openapi-example/commit/4ceae799f6f6b83ffc71cfec5ce13a669e137757
alembic upgrade head
python -i
ausfrom app import models
from app.database import SessionLocal
user = models.User(email='[email protected]', hashed_password='')
db = SessionLocal()
db.add(user)
db.commit()
db.close()
db = SessionLocal()
db.query(models.User).all()
See https://fastapi.tiangolo.com/tutorial/sql-databases/#create-initial-pydantic-models-schemas
Erstellen Sie app / schemas.py
See https://fastapi.tiangolo.com/tutorial/sql-databases/#crud-utils
Erstellen Sie app / crud.py
See https://fastapi.tiangolo.com/tutorial/sql-databases/#main-fastapi-app
app / main.py
Update
Beispiel: https://github.com/tuttieee/fastapi-typescript-openapi-example/commit/1e7d140c1d7929c15f7815648deb14f831807ddd
cURL Beispiel:
curl localhost:8000/users/
curl -X POST -d '{"email": "[email protected]", "password": "test"}' localhost:8000/users/
Von der offenen API http://localhost:8000/docs
MISC
prestart.sh
backend / app / app / main.py
from fastapi.routing import APIRoute
...
def use_route_names_as_operation_ids(app: FastAPI) -> None:
"""
Simplify operation IDs so that generated API clients have simpler function
names.
Should be called only after all routes have been added.
"""
for route in app.routes:
if isinstance(route, APIRoute):
route.operation_id = route.name
use_route_names_as_operation_ids(app)
Frontend Create React App
$ yarn create react-app frontend --template typescript
$ cd frontend
$ yarn start
Beispiel: https://github.com/tuttieee/fastapi-typescript-openapi-example/commit/21b1f0f926132fdbf9c1dbef967ef4286fa27279
--CORS-Einstellungen
backend / app / app / main.py
hinzugefügt# TODO: This is for development. Remove it for production.
origins = [
"<http://localhost:3000",>
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
yarn add axios
frontend / src / App.tsx
zu holenimport React, { useState, useEffect } from 'react';
import './App.css';
import { DefaultApi, Configuration, User } from './api-client';
const config = new Configuration({ basePath: 'http://localhost:8000' }); // TODO: This is for dev
export const apiClient = new DefaultApi(config);
const App: React.FC = () => {
const [users, setUsers] = useState<User[]>([]);
useEffect(() => {
apiClient.readUsers().then((response) => {
setUsers(response.data);
})
})
return (
<div className="App">
<ul>
{users.map(user =>
<li key={user.id}>{user.email}</li>
)}
</ul>
</div>
);
}
export default App;
Beispiel: https://github.com/tuttieee/fastapi-typescript-openapi-example/commit/79fc0bb26c6ffa7e6e43473f0ef497dd1c2f53ff
interface User
Intro OpenAPI: Ehemaliger Swagger FastAPI generiert eine JSON-Definition für OpenAPI: <http: // localhost: 8000 / openapi.json> Open API Generator, der diesen JSON frisst und Clients in verschiedenen Sprachen generiert
See https://openapi-generator.tech/docs/installation.html#docker
docker-compose.openapi-generator.yml
version: "3.7"
services:
openapi-generator:
image: openapitools/openapi-generator-cli
volumes:
- ./frontend:/frontend
working_dir: /frontend
command:
- generate
- -g
- typescript-axios
- -i
- <http://backend/openapi.json>
- -o
- /frontend/src/api-client
- --additional-properties=supportsES6=true,modelPropertyNaming=original
# modelPropertyNaming=original is necessary though camelCase is preferred
# See <https://github.com/OpenAPITools/openapi-generator/issues/2976>
oapi/gen:
docker-compose -f docker-compose.yml -f docker-compose.openapi-generator.yml up openapi-generator \
&& docker-compose -f docker-compose.yml -f docker-compose.openapi-generator.yml rm -f openapi-generator
frontend/src/App.tsx
import React, { useState, useEffect } from 'react';
import './App.css';
import { DefaultApi, Configuration, User } from './api-client';
const config = new Configuration({ basePath: '<http://localhost:8000'> }); // TODO: This is for dev
export const apiClient = new DefaultApi(config);
const App: React.FC = () => {
const [users, setUsers] = useState<User[]>([]);
useEffect(() => {
apiClient.readUsers().then((response) => {
setUsers(response.data);
})
})
return (
<div className="App">
<ul>
{users.map(user =>
<li>{user.email}</li>
)}
</ul>
</div>
);
}
export default App;
Beispiel: https://github.com/tuttieee/fastapi-typescript-openapi-example/commit/1d38242a63c9a5477fa1cde506f36f68a19060a7
Im eigentlichen Projekt werden Unittest, CI, Linter usw. entsprechend übernommen.
Recommended Posts