LoginSignup
0
0

More than 1 year has passed since last update.

FastAPI+React+DockerでQiitaみたいなサイトを作ってみたい -7日目-

Posted at

目次

7日目 - バリデーションの追加

各Modelのバリデーションを追加し、それぞれのエラーハンドリングを適応させていく。

Userモデルのバリデーション

api/v1/models/user.py
# ~~~
from sqlalchemy.orm import relationship,validates
# ~~~
  @validates("login_id")
  def check_user_login_id(self,key,v):
    if v == None:
      raise ValueError("LoginId must not be null")
    if v == "":
      raise ValueError("LoginId must not be empty string")
    if not v.replace('-','').replace('_','').isalnum():
      raise ValueError("LoginId can only contain letters, numbers, _, and -")
    if v[0] == "-" or v[0] == "_":
      raise ValueError('LoginId cannot start with _ or -')
    return v

  @validates("name")
  def check_user_name(self,key,v):
    if v == None:
      raise ValueError("Name must not be null")
    if v == "":
      raise ValueError("Name must not be empty string")
    return v
# ~~~

ただこの場合、passwordはモデルに入るときにはhashにされてしまうのでここではバリデーションできない。
なので一旦crudsファイル内でバリデーションする。(絶対もっといい方法がある。。。)

api/v1/cruds/user.py
  # ~~~~
  def create_user(db:Session,user:user_schema.UserCreateRequest):
    if len(user.password) < 8:
      raise ValueError("Password require at least 8 characters")
    if not user.password.isalnum():
      raise ValueError("Password can only contain letters, numbers")
    password_hash = get_password_hash(user.password)
    new_user = User(
      login_id=user.login_id,
      name=user.name,
      description=user.description,
      password_hash=password_hash
    )
  # ~~~~

これで各部でバリデーションによるエラーを起こすところまでできたので、あとはこのエラーをルーター部分でキャッチする。

api/v1/routers/user.py
# ~~~
@router.post('/users',response_model=user_schema.User)
def create_user(user:user_schema.UserCreateRequest,db:Session = Depends(get_db)):
  db_user = user_crud.get_user_by_login_id(db,user.login_id)
  if db_user:
    raise HTTPException(status_code = 400,detail = "LoginId already exists")
  try:
    new_user = user_crud.create_user(db,user)
  except ValueError as e :
    raise HTTPException(status_code = 400,detail = str(e))
  return new_user
# ~~~

これでバリデーションに引っかかった場合も400でエラー内容を返すことができる。
pydanticでもバリデーションが行えるので、そっちにもバリデーションを追加しておくとより良いかも。

とりあえずこれでbackend側の構築はOK。(足りない場合も今までの実装方法で対応できる。。はず。。。)
次からはフロントエンドを作っていくが、Next.jsを利用した構築にチャレンジしてみようと思うので、次回はまた時間がかかりそう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0