J'ai essayé de créer une API RESTful en connectant l'API rapide du framework Python explosif à MySQL.

Qu'est-ce que FastAPI?

68747470733a2f2f666173746170692e7469616e676f6c6f2e636f6d2f696d672f6c6f676f2d6d617267696e2f6c6f676f2d7465616c2e706e67.png

FastAPI est un framework moderne et explosif pour créer des API pour python3.6 et supérieur.

La caractéristique principale est

(*) D'après les recherches de l'équipe de production FastAPI.

Essayez de lancer le serveur pour le moment

En disant "le code parle plus que les mots", j'aimerais l'utiliser immédiatement.

Tout d'abord, créez un dossier approprié

mkdir fastapi-practice

Installez les packages requis.

pip install fastapi sqlalchemy uvicorn mysqlclient

Si vous n'aimez pas l'installation globale, veuillez l'installer en utilisant la poésie, etc. (j'utiliserai quand même de la poésie après cela).

Créez les fichiers suivants nécessaires pour exécuter FastAPI

touch main.py

Ensuite, écrivez le code comme suit.

main.py


from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def index():
    return {'Hello': 'World'}

Cela seul démarrera le serveur.

uvicorn main:app

Le serveur devrait avoir démarré simplement en tapant. http://localhost:8000/ Si vous essayez d'afficher dans un navigateur, vous devriez voir {" Hello ":" World "}.

Vitesse explosive, API rapide. De plus, Swagger crée automatiquement des spécifications API! !! (surprise!) http://localhost:8000/docs Essayez d'afficher. Les spécifications doivent être faites avec une interface utilisateur élégante.

Vous pouvez même ouvrir un onglet et appuyer sur le bouton «Essayer» pour envoyer une demande et voir la réponse! (Impressionné !!)

スクリーンショット 2020-09-24 14.05.22.png

Au fait http://localhost:8000/redoc Est automatiquement créé et vous pouvez facilement créer des documents plus détaillés! (Trop incroyable !!!)

Utilisez-le réellement (construction de l'environnement docker)

Créons une API RESTful avec Fast API + MySQL en supposant un cas réel.

FastAPI peut être facilement construit avec docker, alors essayons d'exécuter mysql et FastAPI dans le conteneur et de communiquer entre eux.

Commencez par créer docker-compose.yml, docker-sync.yml et Dockerfile dans le dossier.

touch docker-compose.yml docker-sync.yml Dockerfile

Une explication détaillée de l'utilisation de docker est omise ici, mais des informations pour créer un conteneur dans Dockerfile, une commande à exécuter sur le conteneur créé dans docker-compose.yml et un environnement de développement local dans docker-sync.yml Je vais écrire du code pour synchroniser les fichiers dans le conteneur Docker en temps réel.

En ce qui concerne l'utilisation de docker-sync, je pense que les articles suivants écrits par d'autres personnes seront utiles, alors veuillez le lire. Vous pouvez le faire sans utiliser docker-sync, mais je l'utilise pour rendre la vitesse de synchronisation explosive!

https://qiita.com/Satoshi_Numasawa/items/278a143aa41735e1b0da

Maintenant, écrivons le code du Dockerfile.

Dockerfile


FROM python:3.8-alpine
RUN apk --update-cache add python3-dev mariadb-dev gcc make build-base libffi-dev libressl-dev
WORKDIR /app
RUN pip install poetry

Utilisez la poésie pour la gestion des paquets. Il existe également pipenv et pyflow pour la gestion des paquets, alors aimez-vous ça ...?

https://qiita.com/sk217/items/43c994640f4843a18dbe Cet article résume chaque gestionnaire de packages d'une manière facile à comprendre. Si vous êtes intéressé, jetez un œil.

Puis docker-sync.yml

docker-sync.yml


version: "2"
options:
  verbose: true
syncs:
  fastapi-practice-sync:
    src: "."
    notify_terminal: true
    sync_strategy: "native_osx"
    sync_userid: "1000"
    sync_excludes: [".git", ".gitignore", ".venv"]

Et docker-compose.yml

docker-compose.yml


version: "3"
services:
  db:
    image: mysql:latest
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_DATABASE: fastapi_practice_development
      MYSQL_USER: root
      MYSQL_PASSWORD: "password"
      MYSQL_ROOT_PASSWORD: "password"
    ports:
      - "3306:4306"
    volumes:
      - mysql_data:/var/lib/mysql
  fastapi:
    build:
      context: .
      dockerfile: "./Dockerfile"
    command: sh -c "poetry install && poetry run uvicorn main:app --reload --host 0.0.0.0 --port 8000"
    ports:
      - "8000:8000"
    depends_on:
      - db
    volumes:
      - fastapi-sync:/app:nocopy
      - poetry_data:/root/.cache/pypoetry/

volumes:
  mysql_data:
  poetry_data:
  fastapi-sync:
    external: true

L'astuce avec docker-compose.yml est d'utiliser correctement les données persistantes et les données ad hoc. Les données non persistantes seront réinitialisées à chaque fois que docker-compose down.

Dans ce cas, les données de mysql et le package installé par poetry sont rendus persistants afin que les données de mysql ne deviennent pas vides ou que le package n'ait pas besoin d'être téléchargé à chaque démarrage du conteneur. De plus, comme je veux synchroniser le code que j'écris en utilisant docker-sync, j'écris fastapi-practice-sync: / app: nocopy pour l'empêcher d'être synchronisé sans autorisation.

MySQL sera également construit en extrayant la dernière image de docker.

C'est la fin de la configuration du docker.

En fait, utilisez-le (paramètre Fast API)

Tout d'abord, configurez la poésie pour installer les packages requis pour Fast API.

poetry init

Au terminal. Ensuite, la configuration démarrera de manière interactive, alors appuyez sur oui ou non à plusieurs reprises. (Comme il n'y a pas de problème avec les paramètres de base par défaut, je pense qu'il n'y a pas de problème même si vous appuyez sur Entrée à plusieurs reprises ...)

Ensuite, je pense qu'un fichier appelé «pyproject.toml» a été créé.

Les informations de dépendance des packages seront ajoutées ici, alors utilisons la poésie pour installer les packages requis pour lancer l'API Fast.

poetry add fastapi sqlalchemy uvicorn mysqlclient

Saisissez-le et attendez la fin de l'installation du package. Lorsque vous avez terminé, ouvrez pyproject.toml et vous verrez des informations sur les packages installés.

pyproject.toml



[tool.poetry]
name = "fastapi-practice"
version = "0.1.0"
description = ""
authors = ["Your Name <[email protected]>"]

[tool.poetry.dependencies]
python = "^3.8"
fastapi = "^0.61.1"
sqlalchemy = "^1.3.19"
uvicorn = "^0.11.8"

[tool.poetry.dev-dependencies]

[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"

Ensuite, tout ce que vous avez à faire est de taper docker-compose build, de construire l'image et de saisir docker-sync-stack start!

Lors de l'installation d'un nouveau package, installez d'abord le package localement avec poetry add et redémarrez le conteneur docker, et il devrait également être synchronisé à l'intérieur du conteneur!

Émigrer

Ensuite, nous allons créer un lien avec DB (MySQL).

En parlant d'étudier CRUD cette fois, créer une liste Todo! Je vais donc définir la table Todo et effectuer la migration.

Todos Table

column datatype
id integer
title string
content string
done boolean

Nous allons migrer la table avec une telle configuration.

Tout d'abord, créez un fichier qui définit la base de données

touch db.py

J'écrirai le contenu suivant.

db.py



from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker, scoped_session

user_name = "root"
password = "password"
host = "db"
database_name = "fastapi_practice_development"

DATABASE = f'mysql://{user_name}:{password}@{host}/{database_name}'

engine = create_engine(
    DATABASE,
    encoding="utf-8",
    echo=True
)

Base = declarative_base()

SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)


class Todo(Base):
    __tablename__ = 'todos'
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(30), nullable=False)
    content = Column(String(300), nullable=False)
    done = Column(Boolean, default=False)


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


def main():
    Base.metadata.drop_all(bind=engine)
    Base.metadata.create_all(bind=engine)


if __name__ == "__main__":
    main()

FastAPI semble être le courant dominant pour associer une base de données à un objet Python en utilisant l'un des ORM (Object-Relation Mapping) les plus couramment utilisés en Python, appelé sqlalchemy.

Après avoir écrit ceci, il ira dans le conteneur docker et migrera.

docker-sync-stack start

Lancez le conteneur avec, mettez-le en mode synchrone,

docker container ls

Regardez la liste des conteneurs qui est en place. Puis

docker exec -it {Nom du conteneur} sh

Frappez pour entrer dans le conteneur. Ensuite, migrez avec la commande suivante.

poetry run python db.py

Ensuite, la migration s'exécutera en toute sécurité et la table sera créée avec succès!

Ensuite, j'écrirai le traitement CRUD avec Fast API.

Écrivons le traitement CRUD avec FastAPI

Avec l'évolutivité à l'esprit, nous utiliserons la fonction include_router intégrée à l'API Fast pour diviser le fichier.

mkdir routers

Et frappé

touch routers/todo.py

Créez un fichier appelé. J'écrirai ici le processus CRUD.

routers/todo.py


from fastapi import Depends, APIRouter
from sqlalchemy.orm import Session
from starlette.requests import Request
from pydantic import BaseModel
from db import Todo, engine, get_db

router = APIRouter()


class TodoCreate(BaseModel):
    title: str
    content: str
    done: bool


class TodoUpdate(BaseModel):
    title: str
    content: str
    done: bool


@router.get("/")
def read_todos(db: Session = Depends(get_db)):
    todos = db.query(Todo).all()
    return todos


@router.get("/{todo_id}")
def read_todo_by_todo_id(todo_id: int, db: Session = Depends(get_db)):
    todo = db.query(Todo).filter(Todo.id == todo_id).first()
    return todo


@router.post("/")
def create_todo(todo: TodoCreate,  db: Session = Depends(get_db)):
    db_todo = Todo(title=todo.title,
                   content=todo.content, done=todo.done)
    db.add(db_todo)
    db.commit()


@router.put("/{todo_id}")
def update_todo(todo_id: int, todo: TodoUpdate, db: Session = Depends(get_db)):
    db_todo = db.query(Todo).filter(Todo.id == todo_id).first()
    db_todo.title = todo.title
    db_todo.content = todo.content
    db_todo.done = todo.done
    db.commit()


@router.delete("/{todo_id}")
def delete_todo(todo_id: int, db: Session = Depends(get_db)):
    db_todo = db.query(Todo).filter(Todo.id == todo_id).first()
    db.delete(db_todo)
    db.commit()

De cette façon, j'ai grossièrement écrit l'opération CRUD. Écrivez simplement le nom de la requête après @router et l'URL de la cible de l'opération.

Puis éditez main.py pour qu'il puisse être lu.

main.py


from fastapi import FastAPI
from routers import todos

app = FastAPI()


app.include_router(
    todos.router,
    prefix="/todos",
    tags=["todos"],
    responses={404: {"description": "Not found"}},
)

prefix crée le chemin de l'url. les balises sont regroupées pour que les documents soient faciles à voir.

Puis http://localhost:8000/docs Lorsque vous vous connectez, cela devrait ressembler à ceci!

スクリーンショット 2020-09-24 14.53.20.png

Ouvrez l'onglet et appuyez sur le bouton clic pour essayer le processus CRUD!

Si cela est laissé tel quel, une erreur CORS se produira lors de l'appel depuis le front-end, veuillez donc ajouter le traitement CORS suivant lors de l'appel depuis une autre application.

main.py


#Postscript
from starlette.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

Résumé

Comment était FastAPI? Il est très intéressant de pouvoir créer une API avec une si petite quantité de code. Il semble être très compatible lors de la création de microservices avec Python.

Comme il s'agissait du premier message de Qiita, veuillez demander si vous avez des questions! A partir de maintenant, je veux sortir le plus possible sur Qiita ... (je ferai de mon mieux)

Recommended Posts

J'ai essayé de créer une API RESTful en connectant l'API rapide du framework Python explosif à MySQL.
J'ai essayé de créer une API list.csv avec Python à partir de swagger.yaml
J'ai essayé de créer l'API Quip
Django super introduction par les débutants Python! Partie 6 J'ai essayé d'implémenter la fonction de connexion
J'ai essayé de créer un pointage de crédit simple avec régression logistique.
Rubyist a essayé de créer une API simple avec Python + bouteille + MySQL
J'ai créé une bibliothèque Python pour appeler l'API de LINE WORKS
J'ai essayé de créer une liste de nombres premiers avec python
Créer une API REST pour faire fonctionner dynamodb avec le Framework Django REST
J'ai essayé de créer un linebot (implémentation)
J'ai essayé de créer un linebot (préparation)
J'ai essayé de toucher l'API COTOHA
J'ai créé une API Web
J'ai essayé le framework de test Python Tornado
J'ai essayé de vérifier l'identification du locuteur par l'API de reconnaissance du locuteur d'Azure Cognitive Services avec Python. # 1
J'ai essayé de vérifier l'identification du locuteur par l'API de reconnaissance du locuteur d'Azure Cognitive Services avec Python. # 2
J'ai essayé de créer un programme qui convertit les nombres hexadécimaux en nombres décimaux avec python
J'ai essayé d'obtenir le code d'authentification de l'API Qiita avec Python.
J'ai essayé de vérifier et d'analyser l'accélération de Python par Cython
[Outlook] J'ai essayé de créer automatiquement un e-mail de rapport quotidien avec Python
J'ai essayé d'obtenir les informations sur le film de l'API TMDb avec Python
J'ai créé un exemple pour accéder à Salesforce en utilisant Python et Bottle
J'ai essayé de vérifier le résultat du test A / B avec le test du chi carré
J'ai essayé d'analyser la carte du Nouvel An par moi-même en utilisant python
Django super introduction par les débutants Python! Partie 3 J'ai essayé d'utiliser la fonction d'héritage de fichier de modèle
Django super introduction par les débutants Python! Partie 2 J'ai essayé d'utiliser les fonctions pratiques du modèle
Je veux créer une fenêtre avec Python
J'ai essayé d'utiliser le module Datetime de Python
J'ai essayé de créer une classe qui peut facilement sérialiser Json en Python
Créons-le en appliquant Protocol Buffer à l'API avec Serverless Framework.
Quand j'ai essayé de créer un environnement virtuel avec Python, cela n'a pas fonctionné
J'ai essayé de créer facilement un système de présence entièrement automatique avec Selenium + Python
[Python] J'ai essayé d'obtenir le nom du type sous forme de chaîne de caractères à partir de la fonction type
J'ai essayé de créer un modèle avec l'exemple d'Amazon SageMaker Autopilot
Je souhaite créer une API qui retourne un modèle avec une relation récursive dans Django REST Framework
J'ai essayé de représenter graphiquement les packages installés en Python
[CRUD] [Django] Créer un site CRUD en utilisant le framework Python Django ~ 1 ~
J'ai essayé de toucher un fichier CSV avec Python
J'ai essayé de résoudre Soma Cube avec python
J'ai essayé d'implémenter un pseudo pachislot en Python
[Python] J'ai essayé de représenter graphiquement le top 10 des ombres à paupières
[CRUD] [Django] Créer un site CRUD en utilisant le framework Python Django ~ 2 ~
J'ai essayé de résoudre le problème avec Python Vol.1
[CRUD] [Django] Créer un site CRUD en utilisant le framework Python Django ~ 3 ~
[CRUD] [Django] Créer un site CRUD en utilisant le framework Python Django ~ 4 ~
[CRUD] [Django] Créer un site CRUD en utilisant le framework Python Django ~ 5 ~
J'ai essayé de frapper l'API avec le client python d'echonest
J'ai essayé de résumer les opérations de chaîne de Python
J'ai essayé de notifier la mise à jour de "Devenir romancier" en utilisant "IFTTT" et "Devenir un romancier API"
[Python] J'ai essayé de créer automatiquement un rapport quotidien de YWT avec la messagerie Outlook
Utilisez l'API Twitter pour réduire le temps nécessaire à Twitter (créer une chronologie de mise en évidence (comme))
J'ai essayé de créer un cadre de données pandas en grattant les informations de rappel d'aliments avec Python
J'ai essayé de trouver l'entropie de l'image avec python
J'ai essayé de simuler la propagation de l'infection avec Python
J'ai essayé d'implémenter un automate cellulaire unidimensionnel en Python
La première API à créer avec le framework Python Djnago REST