2025/09/26 Flask - 5

김기훈·2025년 9월 26일

TIL

목록 보기
27/191

미니 프로젝트

# add/models.py
                  from sqlalchemy import Column, Integer, String, Text
                  from . import Base

                  class Review(Base):
                      __tablename__ = "reviews"
                      id = Column(Integer, primary_key=True, index=True)
                      title = Column(String(100), nullable=False)
                      content = Column(Text, nullable=False)
                      rating = Column(Integer, nullable=False)

# services/service.py
                  from app import SessionLocal
                  from app.models import Review

                  def create_review(title, content, rating):
                      """리뷰 생성"""
                      db = SessionLocal()
                      review = Review(title=title, content=content, rating=rating)
                      db.add(review)
                      db.commit()
                      return review

                  def get_review_by_id(review_id):
                      """ID로 리뷰 조회"""
                      db = SessionLocal()
                      return db.query(Review).get(review_id)
  • review_id : 그냥 변수 이름일뿐 다른 이름이여도 가능
    • review = Review(title=title, content=content, rating=rating)
      • 함수의 매개변수와 클래스의 컬럼이름과 동일하게 해서 연결
  • 생성된 내용들은 SQLAlchemy + DB 자체 기능으로 자동으로 id값이 붙음
  • 리뷰 조회에서 review_id는 클래스의 컬럼명과 연결은 없지만 .get()이 Review 클래스의 primary key(id)를 기준으로 조회하기 때문에 get(review_id) 라고 하면 review_id 값이 id 컬럼에 자동으로 매칭되는 것처럼 보이는 것

Blueprint

review_bp = Blueprint("review", __name__) : Blueprint 생성

  • Flask 앱에 직접 @app.route로 등록하지 않고,
    • 관련 있는 라우트들을 하나의 그룹으로 묶을 수 있게 해줌
  • 작은 프로젝트는 app.py 안에 모든 라우트를 다 넣어도 괜찮지만,
    • 커지면 유저, 리뷰, 게시글 같은 기능별로 나누는 게 훨씬 좋음
      • Blueprint는 이런 모듈화를 도와줘서 코드를 깔끔하게 관리 가능
# __init__.py

                    from flask import Flask
                    from .routes.review import review_bp

                    def create_app():
                        app = Flask(__name__)
                        app.register_blueprint(review_bp)  # 등록
                        return app
  • Blueprint는 단독으로 실행되는 게 아니라, Flask 앱에 등록해야 합니다.

    • 이렇게 등록해야 실제 @review_bp.route(...) 들이 app에 포함
  • review_bp = Blueprint("review", __name__)

    • 리뷰 관련 라우트들을 모아 두는 블루프린트 생성
      • 장점: 코드 모듈화, 유지보수 용이, 여러 기능을 독립적으로 관리 가능.

# route.py

          @review_bp.route("/new", methods=["GET", "POST"])
          def new_review():
              if request.method == "POST":
                  title = request.form["title"]
                  content = request.form["content"]
                  rating = request.form["rating"]

                  create_review(title, content, rating)

                  return redirect(url_for("review.index"))
                  
              return render_template("new.html")
  • @review_bp.route("/new", methods=["GET", "POST"])
    • /new 경로로 들어오는 GET/POST 요청을 이 함수(new_review)가 처리
  • if request.method == "POST":
    • 현재 요청의 HTTP 메서드가 POST인지 확인
  • title = request.form["title"]
  • content = request.form["content"]
  • rating = request.form["rating"]
    • 사용자가 제출한 HTML <form> 데이터에서 name="title", name="content", name="rating" 값을 꺼내옴
      • 이 값들은 문자열 형태로 전달 , rating도 form에서는 문자열
  • create_review(title, content, rating)
    • create_review 함수를 호출해서 DB에 새로운 Review 객체를 저장
  • return redirect(url_for("review.index"))
    • redirect() : 그 URL로 브라우저를 돌려보내는 역할
    • url_for() : 뷰 함수 이름을 기준으로 URL을 만들어주는 Flask 함수
      • 리뷰를 저장한 뒤, review.index라는 엔드포인트로 리다이렉트합
        • review → 블루프린트 이름 (Blueprint("review", name)
          - index → 블루프린트 안에 있는 뷰 함수 이름 (def index(): ...)
      • url_for("review.index") : 해당 뷰 함수의 실제 URL을 자동으로 찾아줌
    • 즉, 새 리뷰 작성 후 리뷰 목록 페이지로 이동시키는 효과
  • return render_template("new.html")
    • 요청이 POST가 아닌 경우(GET 요청일 때), new.html 템플릿을 렌더링
    • 보통 사용자에게 리뷰 작성 폼을 보여주는 역할

          review_bp = Blueprint("review", __name__)

          @review_bp.route("/")
          def index():
              """리뷰 목록 + 평균 별점"""
              reviews = get_all_reviews()

              avg_rating = round(
                  sum([r.rating for r in reviews]) / len(reviews), 1
              ) if reviews else 0

              return render_template("index.html", reviews=reviews, avg_rating=avg_rating)

          @review_bp.route("/new", methods=["GET", "POST"])
          def new_review():
              
              """새 리뷰 작성"""
              if request.method == "POST":
                  title = request.form["title"]
                  content = request.form["content"]
                  rating = request.form["rating"]ㅇ

                  create_review(title, content, rating)

                  return redirect(url_for("review.index"))

              return render_template("new.html")
  • 사용자가 /new에 접속 : GET 요청 = 링크를 눌러서 들어가면 기본적으로 GET 요청이 됨
    • new_review() 함수가 실행 = new.html 폼 화면이 렌더링 = 화면에 리뷰 작성 폼이 표시
  • 사용자가 /new에 접속 후 폼 작성 후 제출 : POST 요청
    • new_review() 함수에서 request.form[...]으로 값을 꺼냄
    • create_review(...)를 호출해서 DB에 새로운 리뷰 row를 INSERT
  • redirect(url_for("review.index")) : 브라우저가 자동으로 / 로 이동하고 나서 index함수 실행
    • 최종적으로 브라우저에는 index.html이 표시되는데, 그 안에는 방금 작성한 리뷰도 목록에 포함되어 보임

init.py

  • Flask 앱을 생성하고 DB와 연결하는 초기 설정을 모아둔 곳

profile
안녕하세요.

0개의 댓글