Web 10 : Fastapi(2)

haeIT·2024년 8월 19일

Web

목록 보기
10/14
post-thumbnail

2024-08-19 MON


ch7_exception

from fastapi import FastAPI, HHTPException

app = FastAPI()

@app.get("/items/{item_id}") #get 방식으로 item_id(경로매개변수)를 받아온다.
def read_item(item_id : int):
    try:
        if item_id <0:
            raise ValueError("음수는 허용되지 않습니다.") 
            #item_id가 음수일 경우 ValueError를 발생시킨다.
        result = 100/item_id
        return result
        
    except ValueError as e:
        raise HHTPException(status_code=400, detail=str(e)) 
        #HTTPException을 발생시킨다. 
        #status_code는 400, detail은 ValueError의 메세지를 반환한다.
        #raise는 에러를 발생시키는 명령어
        
        

  • 정수 입력시 if문 정상 실행

  • 음수 입력시 예외처리 경고문 실행
  • 이때 raise는 에러를 나타내는 명령어

  • 0 입력시 zero division error 출력
  • 왜? item_id가 0이면 if문 못들어가고 result = 100/item_id로 넘어감. 따라서 아래 코드 처럼 써주면 0에 대해서도 더 깔끔하게 처리 가능할듯?
def read_item(item_id: int):
    try:
        if item_id <= 0:
            raise ValueError("0 또는 음수는 허용되지 않습니다.")
        result = 100 / item_id
        return result
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))

🌈 ValueError

  • 파이썬에 내장된 예외 클래스
  • 함수나 연산에 부적절한 값이 전달되었을 때 발생
  • 별도 import 필요 없음

🌈 HTTPException

  • 웹 프레임워크에서 제공하는 예외클래스
  • 주로 flask나 fastapi에서 多사용중
  • http 응답을 생성하기 위해 사용.
  • http 상태코드를 클라이언트에게 전달(raise 명령어 사용)

ch8_template

폴더 구조

ch8_template
	ㄴ static
    ㄴ template
    ㄴ main.py
  • template 안에 html 파일 들어감
  • static 폴더 안에 css, images, js 들어감
from fastapi import FastAPI, Request, Query
from fastapi.templating import Jinja2Templates
from typing import List
from pydantic import BaseModel

app = FastAPI()

templates = Jinja2Templates(directory="templates") # templates 폴더를 지정

class ItemList(BaseModel):
    items : List[str]

@app.get("/")
def read_root(request: Request): # Request : 클라이언트가 서버에 요청하는 다양한 정보를 가진 객체
    return templates.TemplateResponse("index.html", {"request": request})
    # html script를 리턴함.
    # request 객체도 포함해서 리턴!  

@app.get("/user/{username}")
def get_user(request: Request, username: str):
    return templates.TemplateResponse("index.html", {"request":request, "username":username})

@app.get("/greet")
def greeting(request: Request, time_of_day: str):
    return templates.TemplateResponse("index1.html", {"request":request, "time_of_day":time_of_day})


@app.get("/items")
def read_items(request: Request, my_items:List[str] = Query(...)):
    return templates.TemplateResponse("index2.html", {'request':request, 'items': my_items})

@app.get("/inherit")
def inherit(request: Request):
    return templates.TemplateResponse("index3.html", {"request":request})
  • 안되는중......
  • html로 안넘어가는 이슈 발생
  • 시도해본거
    jinja 다시 설치
    vscode 껐다 키기
    크롬 창 닫기
  • 컴퓨터를 껐다 켰더니 갑자기 됨

  • reload 해주기

  • 같은 방식으로 html코드에 이미지파일 넣어주면 이미지도 가능!

ch9_sqlalchemy

1. sqlalchemy 설치

pip install sqlalchemy==1.4.39

2. pymysql 설치

pip install pymysql==1.1.0

3. db생성하기

  • mysql workbench에 들어가서 db를 먼저 생성해야 아래 코드에서 사용가능
    create database fastapi_db;
  • fastapi_db라는 이름의 데이터 베이스 생성함

4. 준비 끝 코드

from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.ext.declarative import declarative_base
from pydantic import BaseModel  # => pydantic model : 새로운 데이터타입 묶음

database_url = "mysql+pymysql://root:1234@localhost/fastapi_db"
engine = create_engine(database_url)

Base = declarative_base()

# database architecture : database schema

# 테이블 생성 => 객체 => row data 하나
class User(Base): 
    __tablename__ = "users"  # 테이블이름
    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    username = Column(String(50), unique=True, index=True)
    email = Column(String(120))

# pydantic model : 새로운 데이터 타입의 덩어리
class UserCreate(BaseModel):
    username: str
    email: str

# database session 생성하고 관리하는 의존성 함수
def get_db():
    db = Session(bind=engine)
    try:
        yield db   # generate
    except:
        db.close()

# 테이블 생성 명렁 : 테이블이 없으면 새로 생성, 있으면 생성하지 않음
Base.metadata.create_all(bind=engine)

app = FastAPI()

@app.get("/")
def read_root():
    return {"message" : 'Hello, Haein~!'}

@app.post("/users")
def create_user(user: UserCreate, db: Session = Depends(get_db)):
    new_user = User(username=user.username, email = user.email)
    db.add(new_user)
    db.commit()
    db.refresh(new_user)
    return {"id": new_user.id, "username":new_user.username, 'email':new_user.email}
  • from sqlalchemy.ext.declarative import declarative_base : # Orm을 통해서 테이블을 생성가능. 상속
  • from pydantic import BaseModel : Basemodel을 이용해서 pydantic 모델을 만듦( 새로운 데이터타입 묶음)
  • engine = create_engine(database_url) : 데이터베이스 연결하는 객체 engine을 생성함
  • Base = declarative_base() : ORM을 사용하기 위한 객체 생성

  • Talend API 접속

  • post 방식으로 정의 했으니까 post 선택 후 json 형식으로 데이터 추가해줌

  • send 하면 데이터 베이스에 저장됨

  • post 방식 확인은 workbench에서만 가능!

  • 브라우저에서 확인하려면 html 만들어야함.

  • 잘 저장되어 있음~!

  • 근데 이상한 점!!
    id = Column(Integer, primary_key=True, index=True, autoincrement=True) 에서 내가 지정한 대로 id 값이 안들어감

  • 이렇게 id 값을 333을 줬지만 확인해보면

  • autoincrement가 자동으로 적용되어 들어감

  • 강사님 답변 => 원래 autoincrement를 True로 주면 따로 id값을 지정 안하는게 국룰임. 근데 원래는 지정한 값 그대로 들어가야 맞음. 왜그런지는 모르겠다.

  • 🍀CLOVA Says🍀

    아놔 언제바뀜

  • db 연동하는거 중요합니다~!

  • 다른 방식


  • session 객체 생성해서 사용하는 방식임

  • 장점?
    session을 정교하게 관리할 수 있다.

  • 단점?
    session을 자동으로 close하지 않는다.(자원낭비)

  • 결과는 똑같고 방식이 조금 다름

  • 첫번째 방법이 더 권장되는 방식임


alchemy query 연습하기

  • 꼭 알아두기~!
db.query(User.username).all() 
# select username from users;

db.query(User).filter(User.username =='haein').first() 
# select * from users where username = 'haein' limit 1;

db.query(User).filter(User.username =='Ham').filter(User.email=='ham@naver.com').first()

db.query(User).order_by(User.username).all() 
# select * from users order by username;

db.query(User).order_by(desc(User.username)).all() 
# select * from users order by username desc;

db.query(User).limit(5).all() 
# select * from users limit 5;

db.query(User).limit(2).all() 
# select * from users limit 2;

figma

2개의 댓글

comment-user-thumbnail
2024년 8월 20일

덕분에 겨우겨우 수업 따라갔네요^^;;; 꼼꼼한 정리 감사합니다~^^

1개의 답글