Closed37

FastAPI

ganyariyaganyariya

https://fastapi.tiangolo.com/ja/tutorial/schema-extra-example/

Swaggerに反映できるスキーマを設定できる

from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    tax: Optional[float] = None

    class Config:
        schema_extra = {
            "example": {
                "name": "Foo",
                "tax": 3.2,
            }
        }


@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
    results = {"item_id": item_id, "item": item}
    return results

ganyariyaganyariya

https://fastapi.tiangolo.com/ja/tutorial/response-model/#data-with-the-same-values-as-the-defaults

response_modelで返すJSONのスキーマを設定できる
BaseModelで絞ることが可能

from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel, EmailStr

app = FastAPI()


class UserIn(BaseModel):
    username: str
    password: str
    email: EmailStr
    full_name: Optional[str] = None


class UserOut(BaseModel):
    username: str
    email: EmailStr
    full_name: Optional[str] = None


@app.post("/user/", response_model=UserOut)
async def create_user(user: UserIn):
    return user

ganyariyaganyariya

https://fastapi.tiangolo.com/ja/tutorial/extra-models/

Userに関するものを扱うときに

  • postで入力される
  • DBに入れる(ハッシュ)
  • 返す(パスワードを含まない)

をするときにそれぞれClassでやるとこわいので 
Baseを作ってそれを継承しよう

from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel, EmailStr

app = FastAPI()


class UserBase(BaseModel):
    username: str
    email: EmailStr
    full_name: Optional[str] = None


class UserIn(UserBase):
    password: str


class UserOut(UserBase):
    pass


class UserInDB(UserBase):
    hashed_password: str


def fake_password_hasher(raw_password: str):
    return "supersecret" + raw_password


def fake_save_user(user_in: UserIn):
    hashed_password = fake_password_hasher(user_in.password)
    user_in_db = UserInDB(**user_in.dict(), hashed_password=hashed_password)
    print("User saved! ..not really")
    return user_in_db


@app.post("/user/", response_model=UserOut)
async def create_user(user_in: UserIn):
    user_saved = fake_save_user(user_in)
    return user_saved
ganyariyaganyariya

Formを受け取ることができる()

from fastapi import FastAPI, Form

app = FastAPI()


@app.post("/login/")
async def login(username: str = Form(...), password: str = Form(...)):
    return {"username": username}
ganyariyaganyariya

https://fastapi.tiangolo.com/ja/tutorial/dependencies/classes-as-dependencies/

依存性注入。
外部から変更を受け付けるように設計することによって

  • テストしやすい
  • 変更しやすい
  • スタブなどを作成しやすい
  • 動作を変更しやすい

などに作成できる。
外部から操作できるように作ることが大事であり、FastAPIはそれができるように(外部から操作を受け付けるように)作られている

ganyariyaganyariya

https://dev.classmethod.jp/articles/authentication-and-authorization/

認証: Authentication
相手がかを判別する・識別すること
相手がわかったからと言ってすべてのリソースにアクセスを当然許すわけではない

認可: Authorization
リソースに権限を与えること
「認証」されたからアカウントへの「認可」・ツイートの「認可」を与える

ganyariyaganyariya

https://fastapi.tiangolo.com/ja/tutorial/security/get-current-user/

依存性注入によって、かんたんに今のユーザを取り出せる

class User(BaseModel):
    username: str
    email: Optional[str] = None
    disabled: Optional[bool] = None


def fake_decode_token(token):
    return User(
        username=token + 'fakedecoded',
        email='example@com',
    )


async def get_current_user(token: str = Depends(oauth2_scheme)):
    user = fake_decode_token(token)
    return user


@app.get('/users/me')
async def read_users_me(current_user: User = Depends(get_current_user)):
    return current_user

ganyariyaganyariya

https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/

OAuth2とPasswordの認証チュートリアル

bearerはOAuth2の一つで、ユーザ名とパスワードで認証し、アクセストークンでユーザかを判定するっぽい(ここ実際に実装して勉強がいる)

oauth2_scheme = OAuth2PasswordBearer(tokenUrl='token')で、tokenのパスを指定してSwaggerがtokenパスでログインできるようになっている

ユーザにはトークンを返してあげる
そして、ユーザからアクセスされたトークンが正しければOK

ganyariyaganyariya

https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/

JWTを使って認証のトークンを作成する。
POSTでusernamepasswordを受け取る。(この名前にOpenAPIで規定されている)。
そして、passwordをサーバーでハッシュして、返却データのヘッダを作成する。
これらのヘッダ+データ+シグネチャをJWTとしてBase64したものをトークンとして返す。

ユーザはこのトークンをブラウザにアクセスするときに渡すのでそれをサーバーが確認する。
このトークンとJWTでデコードしてそれがあっていればOK.
また、サーバからJWTで返されるデータはペイロードとしてブラウザが持ち続ける...?(ここ毎回やらないといけないのかわかってないので調べる)

ganyariyaganyariya

https://fastapi.tiangolo.com/tutorial/sql-databases/

SQLとの連携。
ORMは、テーブル(複数形)と 言語におけるクラスを一致させる。各行がインスタンスに相当する。

スキーマ自体はpydanticで作成する。
これによって、リクエスト時やDocsで型を付けて、間違えたリクエストはFastAPI側で破棄できる。

実際にテーブルを操作するときは、modelをSQLAlchemeyで作成して、SQLAlchemy側で操作する。

CRUD関数を作成して、これらのmodelschema(pydantic)の間を取り持っている。

ganyariyaganyariya

https://fastapi.tiangolo.com/tutorial/bigger-applications/

ファイルの分割例。
Pythonのモジュールも含めてすごく丁寧に説明されている(すごい)。

routersを作って、特定のクラスごとに書いても良い。
ただ、これやるとデータベース周りとどうしようかな...
schemasmodelsから読み込めばいいんかな

Routerを使うとあるクエリパス以下ごとに作れるので嬉しい

このスクラップは2020/12/30にクローズされました