실습_블로그 구현 (Flask-MySQL를 활용)
이번 실습에서는 Flask와 MySQL을 활용하여 간단한 블로그 시스템을 구현합니다. 블로그 시스템은 사용자에게 게시물을 생성, 조회, 수정 및 삭제할 수 있는 기능을 제공합니다. 아래에서는 전체 코드를 제시한 후, 각 프로세스를 단계별로 설명하겠습니다.
프로젝트 구조
my_flask_app/
│
├── app.py # Flask 애플리케이션 설정 및 라우팅
├── posts_routes.py # 게시물 관련 라우트 처리
├── db.yaml # 데이터베이스 연결 정보
└── templates/
├── posts.html # 게시물 리스트 및 작성 폼
└── post.html # 개별 게시물 표시
이번 코드는 게시글 CRUD (생성, 조회, 수정, 삭제) 기능을 제공하는 API의 라우트와 뷰 함수를 구현한 부분입니다. 이를 위해 Flask와 Flask-Smorest를 사용하여 RESTful API 스타일로 작성되었으며, MySQL 데이터베이스와의 상호작용을 위해 Flask-MySQLdb를 사용하고 있습니다.
아래는 각 기능을 단계별로 설명한 내용입니다.
전체 코드 (posts_routes.py)
from flask import request, jsonify
from flask_smorest import Blueprint, abort
def create_posts_blueprint(mysql):
posts_blp = Blueprint(
"posts",
__name__,
description="posts api",
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 또는 content가 없습니다.")
sql = "INSERT INTO posts(title, content) VALUES(%s, %s)"
cursor.execute(sql, (title, content))
mysql.connection.commit()
return jsonify({"message": "success"}), 201
# 게시글 상세 조회, 수정 및 삭제
@posts_blp.route("/<int:id>", methods=["GET", "PUT", "DELETE"])
def post(id):
cursor = mysql.connection.cursor()
# 게시글 상세 조회
if request.method == "GET":
sql = f"SELECT * FROM posts WHERE id={id}"
cursor.execute(sql)
post = cursor.fetchone()
if not post:
abort(404, message="해당 게시글이 없습니다.")
return {
"id": post[0],
"title": post[1],
"content": post[2],
}
# 게시글 수정
elif request.method == "PUT":
title = request.json.get("title")
content = request.json.get("content")
if not title or not content:
abort(400, message="title 또는 content가 없습니다.")
sql = "SELECT * FROM posts WHERE id=%s"
cursor.execute(sql, (id,))
post = cursor.fetchone()
if not post:
abort(404, message="해당 게시글이 없습니다.")
sql = "UPDATE posts SET title=%s, content=%s WHERE id=%s"
cursor.execute(sql, (title, content, id))
mysql.connection.commit()
return jsonify({"message": "Successfully updated title & content"})
# 게시글 삭제
elif request.method == "DELETE":
sql = "SELECT * FROM posts WHERE id=%s"
cursor.execute(sql, (id,))
post = cursor.fetchone()
if not post:
abort(404, message="해당 게시글이 없습니다.")
sql = "DELETE FROM posts WHERE id=%s"
cursor.execute(sql, (id,))
mysql.connection.commit()
return jsonify({"message": "Successfully deleted post"})
return posts_blp
1. create_posts_blueprint 함수
이 함수는 Flask 애플리케이션에서 사용할 블루프린트를 정의합니다. 블루프린트는 Flask에서 여러 개의 라우트를 그룹화하여 모듈화할 수 있게 해주는 기능입니다. 이 함수는 mysql 객체를 받아 게시글 관련 라우트를 설정합니다.
Blueprint 설정
posts_blp = Blueprint(
"posts",
__name__,
description="posts api",
url_prefix="/posts",
)
- Blueprint: "posts"라는 이름의 블루프린트를 생성하고, /posts라는 URL 프리픽스를 설정합니다. 이후 이 블루프린트에 정의된 모든 라우트는 /posts로 시작합니다.
2. GET 및 POST 요청 처리
게시글 목록 조회 (GET /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)
- 목표: MySQL 데이터베이스에서 모든 게시글을 조회하여 JSON 형식으로 반환합니다.
- 동작:
- GET 요청 시, SELECT * FROM posts 쿼리를 실행하여 모든 게시글을 조회합니다.
- 조회된 게시글들을 post_list에 담고, 이를 jsonify로 JSON 형태로 반환합니다.
게시글 생성 (POST /posts)
elif request.method == "POST":
title = request.json.get("title")
content = request.json.get("content")
if not title or not content:
abort(400, message="title 또는 content가 없습니다.")
sql = "INSERT INTO posts(title, content) VALUES(%s, %s)"
cursor.execute(sql, (title, content))
mysql.connection.commit()
return jsonify({"message": "success"}), 201
- 목표: 클라이언트로부터 게시글의 제목과 내용을 받아 새로운 게시글을 생성합니다.
- 동작:
- POST 요청 시, 요청 본문에서 title과 content 값을 받아옵니다.
- 제목 또는 내용이 없으면 400 상태 코드와 함께 오류 메시지를 반환합니다.
- INSERT INTO posts 쿼리를 실행하여 게시글을 추가하고, 변경 사항을 커밋한 후 성공 메시지를 반환합니다.
3. 게시글 상세 조회, 수정, 삭제 (GET /posts/<int:id>, PUT /posts/<int:id>, DELETE /posts/<int:id>)
게시글 상세 조회 (GET /posts/<id>)
@posts_blp.route("/<int:id>", methods=["GET", "PUT", "DELETE"])
def post(id):
cursor = mysql.connection.cursor()
if request.method == "GET":
sql = f"SELECT * FROM posts WHERE id={id}"
cursor.execute(sql)
post = cursor.fetchone()
if not post:
abort(404, message="해당 게시글이 없습니다.")
return {
"id": post[0],
"title": post[1],
"content": post[2],
}
- 목표: 특정 게시글을 조회합니다.
- 동작:
- GET 요청 시, SELECT * FROM posts WHERE id={id} 쿼리를 실행하여 특정 게시글을 조회합니다.
- 해당 게시글이 없으면 404 오류를 반환하고, 존재하면 게시글 데이터를 JSON 형식으로 반환합니다.
게시글 수정 (PUT /posts/<id>)
elif request.method == "PUT":
title = request.json.get("title")
content = request.json.get("content")
if not title or not content:
abort(400, message="title 또는 content가 없습니다.")
sql = "SELECT * FROM posts WHERE id=%s"
cursor.execute(sql, (id,))
post = cursor.fetchone()
if not post:
abort(404, message="해당 게시글이 없습니다.")
sql = "UPDATE posts SET title=%s, content=%s WHERE id=%s"
cursor.execute(sql, (title, content, id))
mysql.connection.commit()
return jsonify({"message": "Successfully updated title & content"})
- 목표: 특정 게시글의 제목과 내용을 수정합니다.
- 동작:
- PUT 요청 시, 요청 본문에서 title과 content 값을 받아옵니다.
- 해당 게시글이 존재하지 않으면 404 오류를 반환합니다.
- 게시글이 존재하면 UPDATE 쿼리를 실행하여 제목과 내용을 수정하고, 성공 메시지를 반환합니다.
게시글 삭제 (DELETE /posts/<id>)
elif request.method == "DELETE":
sql = "SELECT * FROM posts WHERE id=%s"
cursor.execute(sql, (id,))
post = cursor.fetchone()
if not post:
abort(404, message="해당 게시글이 없습니다.")
sql = "DELETE FROM posts WHERE id=%s"
cursor.execute(sql, (id,))
mysql.connection.commit()
return jsonify({"message": "Successfully deleted post"})
- 목표: 특정 게시글을 삭제합니다.
- 동작:
- DELETE 요청 시, 해당 게시글이 존재하지 않으면 404 오류를 반환합니다.
- 존재하면 DELETE 쿼리를 실행하여 게시글을 삭제하고, 성공 메시지를 반환합니다.
마무리
이 코드는 게시글 CRUD 기능을 제공하는 API의 라우트와 뷰 함수입니다. Flask의 Blueprint를 사용하여 게시물 관련 라우트를 모듈화하고, MySQL 데이터베이스와 상호작용하여 게시물을 생성, 조회, 수정 및 삭제할 수 있게 구현했습니다. Flask-Smorest의 abort 함수를 사용하여 유효하지 않은 요청에 대한 오류 처리를 하고, 각 요청에 대해 적절한 HTTP 상태 코드와 메시지를 반환합니다.
'Flask' 카테고리의 다른 글
Chapter 4-8 HTTP 기본 인증 Basic Authentication, Flask-HTTPAuth (0) | 2025.04.22 |
---|---|
Chapter 4-7 Flask Authentication/ Session 인증 방식 (0) | 2025.04.22 |
Chapter 4-4 실습_블로그 구현 (Flask-MySQL를 활용) MySQL 쿼리, db.yaml (0) | 2025.04.22 |
Chapter 4-3 실습_블로그 구현 (Flask-MySQL를 활용) templates/posts.html (0) | 2025.04.22 |
Chapter 4-2 실습_블로그 구현 (Flask-MySQL를 활용) (0) | 2025.04.22 |