과제

Flask practice blog 구축 API 라우트 설정 posts_routes.py (2/3)

Chansman 2025. 4. 22. 18:21

📌 posts_routes.py - 게시글 관련 API 라우트 설정

posts_routes.py는 Flask에서 블로그 게시글 관련 API 라우트를 정의하는 파일입니다. 이 파일은 게시글을 생성, 조회, 수정, 삭제하는 다양한 API 엔드포인트를 처리합니다. Flask-Smorest의 Blueprint를 사용하여 API를 분리하여 관리하고 있습니다.

1. create_posts_blueprint() 함수 정의

def create_posts_blueprint(mysql):
  posts_blp = Blueprint("posts", __name__, description="Operations on posts", url_prefix="/posts")
  • Blueprint: Flask에서 여러 라우트를 모듈화하기 위해 사용되는 객체입니다. Blueprint는 여러 개의 라우트를 하나로 묶어 관리할 수 있게 해줍니다.
  • posts_blp: Blueprint 객체로, url_prefix="/posts"로 설정하여 /posts 경로 하위에 있는 모든 라우트를 설정합니다.

2. 게시글 조회 및 생성 (GET, POST)

@posts_blp.route('/', methods=['GET', 'POST'])
def posts():
  cursor = mysql.connection.cursor()
  
  # 게시글 조회 (GET 요청)
  if request.method == 'GET':
    sql = "SELECT * FROM posts"
    cursor.execute(sql)
    
    posts = cursor.fetchall()
    cursor.close()
    
    post_list = []
    
    for post in posts:
      post_list.append({
        'id': post[0],
        'title': post[1],
        'content': post[2]
      })
      
    return jsonify(post_list)
  • GET 요청 처리: MySQL에서 모든 게시글을 조회하여 반환합니다.
    • cursor.fetchall()을 통해 posts 테이블에 저장된 모든 데이터를 가져옵니다.
    • post_list 리스트에 각 게시글의 id, title, content를 저장하고 jsonify()로 JSON 형식으로 반환합니다.
  # 게시글 생성 (POST 요청)
  elif request.method == 'POST':
    title = request.json.get('title')
    content = request.json.get('content')        
    
    if not title or not content:
      abort(400, message="Title or Content cannot be empty")
      
    sql = 'INSERT INTO posts(title, content) VALUES(%s, %s)'
    cursor.execute(sql, (title, content))
    mysql.connection.commit()
    
    return jsonify({'msg': "successfully created post data", "title": title, "content": content}), 201
  • POST 요청 처리: 새 게시글을 생성합니다.
    • 요청 본문에서 title과 content를 받아오고, 둘 중 하나라도 비어 있으면 400 에러를 반환합니다.
    • INSERT INTO posts SQL 쿼리를 사용하여 새로운 게시글을 데이터베이스에 삽입하고, 성공 메시지를 반환합니다.

3. 특정 게시글 조회, 수정, 삭제 (GET, PUT, DELETE)

@posts_blp.route('/<int:id>', methods=["GET", "PUT", "DELETE"])
def post(id):
  cursor = mysql.connection.cursor()
  sql = "SELECT * FROM posts WHERE id=%s"
  cursor.execute(sql, (id,))
  post = cursor.fetchone()
  • <int:id>: URL 경로에서 id 파라미터를 받아 특정 게시글을 조회, 수정, 삭제하는 라우트입니다.
  # 게시글 조회 (GET 요청)
  if request.method == 'GET':
    if not post:
      abort(404, "Not found post")
    return {
        'id': post[0],
        'title': post[1],
        'content': post[2]
    }
  • GET 요청 처리: 특정 id를 가진 게시글을 조회합니다.
    • cursor.fetchone()을 사용해 하나의 게시글을 조회합니다.
    • 게시글이 존재하지 않으면 404 에러를 반환합니다.
  # 게시글 수정 (PUT 요청)
  elif request.method == 'PUT':
    title = request.json.get('title')
    content = request.json.get('content')
    
    if not title or not content:
      abort(400, "Not Found Title, Content")
    
    if not post:
      abort(404, "Not Found Post")
      
    sql = "UPDATE posts SET title = %s, content = %s WHERE id = %s"
    cursor.execute(sql, (title, content, id))
    mysql.connection.commit()
    
    return jsonify({"msg": "Successfully updated title and content"})
  • PUT 요청 처리: 게시글의 title과 content를 수정합니다.
    • 수정할 제목과 내용을 request.json에서 받아오고, 비어 있으면 400 에러를 반환합니다.
    • 특정 게시글이 존재하지 않으면 404 에러를 반환하고, UPDATE SQL 쿼리로 게시글을 수정한 후 성공 메시지를 반환합니다.
  # 게시글 삭제 (DELETE 요청)
  elif request.method == 'DELETE':
    if not post:
      abort(400, "Not Found Title, Content")
    sql = "DELETE FROM posts WHERE id=%s"
    cursor.execute(sql, (id,))
    mysql.connection.commit()

    return jsonify({"msg":"Successfully deleted title and content"})
  • DELETE 요청 처리: 특정 id를 가진 게시글을 삭제합니다.
    • 게시글이 존재하지 않으면 400 에러를 반환하고, 존재하면 DELETE SQL 쿼리로 해당 게시글을 삭제한 후 성공 메시지를 반환합니다.

4. create_posts_blueprint() 함수 종료

  return posts_blp
  • 이 함수는 최종적으로 정의된 posts_blp 블루프린트를 반환하여, Flask 애플리케이션에서 사용할 수 있게 합니다.

🚦 동작 원리 및 코드 흐름

  1. 블루프린트 등록: create_posts_blueprint() 함수가 호출되면, 게시글과 관련된 여러 API 기능이 posts_blp라는 블루프린트로 등록됩니다.
  2. 게시글 조회 (GET): /posts 경로로 GET 요청이 들어오면, MySQL에서 모든 게시글을 조회하여 JSON 형식으로 반환합니다.
  3. 게시글 생성 (POST): /posts 경로로 POST 요청이 들어오면, 새 게시글을 MySQL에 삽입하고 성공 메시지를 반환합니다.
  4. 특정 게시글 조회, 수정, 삭제 (GET, PUT, DELETE): /posts/<id> 경로로 GET, PUT, DELETE 요청이 들어오면, 해당 id에 맞는 게시글을 조회, 수정, 삭제합니다.

💻 코드 예시 및 흐름 분석

  • 게시글 조회: /posts로 GET 요청이 들어오면, SELECT * FROM posts 쿼리로 모든 게시글을 조회하여 반환합니다.
  • 게시글 생성: /posts로 POST 요청이 들어오면, 새 게시글을 INSERT INTO posts 쿼리로 MySQL에 추가합니다.
  • 게시글 수정: /posts/<id>로 PUT 요청이 들어오면, UPDATE posts SET title = %s, content = %s 쿼리로 해당 게시글을 수정합니다.
  • 게시글 삭제: /posts/<id>로 DELETE 요청이 들어오면, DELETE FROM posts 쿼리로 해당 게시글을 삭제합니다.

from flask import request, jsonify
from flask_smorest import Blueprint, abort

def create_posts_blueprint(mysql):
  posts_blp = Blueprint("posts",__name__, description="Operations on posts", url_prefix="/posts")

  @posts_blp.route('/', methods=['GET', 'POST'])
  def posts():
    
    cursor = mysql.connection.cursor()
    
    # 게시글 조회
    if request.method == 'GET':
      sql = "SELECT * FROM posts"
      cursor.execute(sql)
      
      posts = cursor.fetchall()
      cursor.close()
      
      post_list = []
      
      for post in posts:
        post_list.append({
          'id' :post[0],
          'title' :post[1],
          'content' :post[2]
        })
        
      return jsonify(post_list)
    
    # 게시글 생성
    elif request.method == 'POST':
      title = request.json.get('title')      
      content = request.json.get('content')        
      
      if not title or not content:
        abort(400, message="Title or Content cannot be emppty")    
        
      sql = 'INSERT INTO posts(title, content) VALUES(%s, %s)'
      cursor.execute(sql, (title,content))
      mysql.connection.commit()
      
      return jsonify({'msg': "successfully created post data", "title":title, "content":content}), 201
    
    # 게시글 수정 및 삭제
    # 특정 게시글만 조회하고싶을 경우
  @posts_blp.route('/<int:id>', methods=["GET", "PUT", "DELETE"])
  def post(id):
    cursor = mysql.connection.cursor()
    sql = "SELECT * FROM posts WHERE id=%s"
    cursor.execute(sql, (id,))
    post = cursor.fetchone()
      
    if request.method == 'GET':
            
      if not post:
        abort(404, "Not found post")
      return ({
          'id' :post[0],
          'title' :post[1],
          'content' :post[2]
        })
        
    elif request.method == 'PUT':
      # data = request.json # 이렇게 작업해도된다.
      # title = data['title']
      
      title = request.json.get('title')
      content = request.json.get('content')
      
      if not title or not content:
        abort(400, "Not Found Title, Content")
      
      if not post:
        abort(404, "Not Found Post")
          
      sql = "UPDATE posts SET title = %s, content = %s WHERE id = %s"
      cursor.execute(sql, (title, content, id))  # title, content, id를 튜플로 전달
      mysql.connection.commit()
      
      return jsonify({"msg": "Successfully updated title and content"})
    
    elif request.method == 'DELETE':
      if not post:
        abort(400, "Not Found Title, Content")
      sql = "DELETE FROM posts WHERE id=%s"
      cursor.execute(sql, (id,))
      mysql.connection.commit()

      return jsonify({"msg":"Successfully deleted title and content"})
    
  return posts_blp

 

✅ 마무리 요약 및 복습 포인트

  • Blueprint를 사용하여 게시글 관련 API 라우트를 모듈화했습니다.
  • GET, POST, PUT, DELETE 메서드를 사용하여 게시글을 조회, 생성, 수정, 삭제하는 기능을 구현했습니다.
  • 각 API에서 MySQL 데이터베이스와 상호작용하여 게시글을 관리하는 방식에 대해 이해했습니다.