ローカル環境以外で無料でweb api を叩きたかったので
heroku を利用して、どこからでもapiを叩ける環境を準備した時の手順を残しておく。
環境
macOS Monterey 12.4
python3.8.9
heroku アカウント作成済み
記事参考にした場合の最終的なディレクトリ構成は以下のようになります。
├── Procfile
├── crud.py
├── database.py
├── main.py
├── models.py
├── requirements.txt
├── runtime.txt
├── schemas.py
└
├── crud.py
├── database.py
├── main.py
├── models.py
├── requirements.txt
├── runtime.txt
├── schemas.py
└
容量抑えるためにpython仮想環境を利用推奨
1 2 3 4 |
python -m venv venv source venv/bin/activate # pip install -r requirements.txt |
ファイル
requirement.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 |
anyio==3.6.1 click==8.1.3 fastapi==0.78.0 gunicorn==20.1.0 h11==0.13.0 idna==3.3 psycopg2-binary==2.9.3 pydantic==1.9.1 sniffio==1.2.0 SQLAlchemy==1.4.39 starlette==0.19.1 typing-extensions==4.3.0 uvicorn==0.18.2 |
1 |
runtime.txt(herokuデプロイ環境で動作させるpythonのversion)
1 |
python-3.8.9 |
main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
from typing import List from fastapi import Depends, FastAPI, HTTPException,UploadFile from sqlalchemy.orm import Session import crud import models import schemas from database import SessionLocal, engine import uvicorn from pydantic import BaseModel models.Base.metadata.create_all(bind=engine) app = FastAPI() # Dependency def get_db(): db = SessionLocal() try: yield db finally: db.close() @app.post("/users/", response_model=schemas.User) def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)): db_user = crud.get_user_by_email(db, email=user.email) if db_user: raise HTTPException(status_code=400, detail="Email already registered") return crud.create_user(db=db, user=user) @app.get("/users/", response_model=List[schemas.User]) def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): users = crud.get_users(db,) return users if __name__ == '__main__': uvicorn.run(app=app) |
database.py
1 2 3 4 5 6 7 8 9 10 11 12 13 |
from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker SQLALCHEMY_DATABASE_URL = "postgresql://user:user@localhost:5432/postgres" engine = create_engine( SQLALCHEMY_DATABASE_URL, ) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) Base = declarative_base() |
models.py
1 2 3 4 5 6 7 8 9 10 11 12 13 |
from sqlalchemy import Boolean, Column, Integer, String from sqlalchemy.orm import relationship from database import Base class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) email = Column(String, unique=True, index=True) hashed_password = Column(String) is_active = Column(Boolean, default=True) |
schemas.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from typing import List from pydantic import BaseModel class UserBase(BaseModel): pass class UserCreate(UserBase): password: str email: str class User(UserBase): id: int class Config: orm_mode = True |
crud.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
from sqlalchemy.orm import Session import models import schemas def get_user(db: Session, user_id: int): return db.query(models.User).filter(models.User.id == user_id).first() def get_user_by_email(db: Session, email: str): return db.query(models.User).filter(models.User.email == email).first() def get_users(db: Session): a = db.query(models.User.id).select_from(models.User).all() a = list(map(lambda x:dict(x),a)) print(a) return a def create_user(db: Session, user: schemas.UserCreate): fake_hashed_password = user.password + "notreallyhashed" db_user = models.User(email=user.email, hashed_password=fake_hashed_password) db.add(db_user) db.commit() db.refresh(db_user) return db_user |
動作確認
1 |
uvicorn main:app --reload |
実行後 http://localhost:8000/docs#/ に接続できたらlocalでの実装は問題ない!
heroku deploy
Procfileの作成 下記のように記述する
1 2 |
web: gunicorn -w 3 -k uvicorn.workers.UvicornWorker main:app |
herokuでプロジェクトを作成するための実行コマンド
1 |
heroku create |
heroku 側でアプリが作られているためpostgresのadd-ons
を追加する
Resources>>検索からHerokuPostgres>>Submit over form
追加後 Heroku Postgres からリンク先に移動
Settings>>Database Credentials >>URI
これをdatabase.pyのSQLALCHEMY_DATABASE_URL
の値に変える
1 2 3 4 |
SQLALCHEMY_DATABASE_URL = "postgresql://user:user@localhost:5432/postgres"" SQLALCHEMY_DATABASE_URL = "postgresql://~~~" |
deploy実行
1 2 3 4 5 6 |
heroku login git init heroku git:remote -a {my-app} git add . git commit -am "make it better" git push heroku master |
コミットできたら
https://<YOUR_HEROKU_APP_NAME>.herokuapp.com/docsで確認してみましょう。
無事疎通が確認できたら
1 |
heroku logs --tail |
でログを確認できると思います。
最後に
無料である程度使えるのでheroku最高!
コメント