[천재교육] 프로젝트 기반 빅데이터 서비스 개발자 양성 과정 9기
학습일 : 2024.08.09
📕 학습 목록
- Flask 이용하여 애플리케이션 제작
📗 기억할 내용
1) 코드 전문 뜯어보기
- Flask를 이용하여 로그인/로그아웃, 게시판 페이지 제작
```python
# Flask 라이브러리에서 Flask 클래스와 관련된 여러 기능을 가져옴
from flask import Flask, jsonify, redirect, render_template, request, session, url_for
# db.py 파일에 있는 함수 호출 (데이터베이스 연결 함수)
from connection import db_connect
# [1. Flask 앱 초기화 및 설정]
app = Flask(__name__) # Flask 애플리케이션 객체 생성
app.debug = True # 디버그 모드 활성화: 서버 코드 수정 시 자동으로 반영됨
app.secret_key = "j0CZF9SS7N97xwajCEnmQxVrzT93Kvfn" # 세션 관리용 비밀 키 설정
@app.route("/") # 루트 경로("/")에 대한 요청 처리 함수 정의
def index():
return render_template("index.html") # index.html 템플릿을 렌더링하여 반환
# [2-1. 로그인 페이지 생성]
@app.route("/login", methods=["GET", "POST"]) # "/login" 경로에 GET과 POST 요청 허용
def login():
SQL = """
SELECT *
FROM
tb_user
WHERE 1=1
AND login_id = %s
AND login_password = %s
""" # 사용자를 인증하기 위한 SQL 쿼리
error_message = None # 오류 메시지 초기화
if request.method == "POST": # POST 요청이 들어올 경우 (로그인 시도)
login_id = request.form["login_id"] # 폼에서 입력된 login_id 가져오기
login_password = request.form["login_password"] # 폼에서 입력된 login_password 가져오기
with db_connect() as conn: # 데이터베이스 연결
with conn.cursor() as cur: # 데이터베이스 커서 생성
cur.execute(SQL, [login_id, login_password]) # SQL 쿼리 실행
user = cur.fetchone() # 첫 번째 결과(한 명의 사용자)를 가져옴
if user != None and len(user) > 0: # 사용자가 존재하면
session["user"] = user # 세션에 사용자 정보 저장
return redirect(url_for("index")) # 메인 페이지로 리디렉션
else:
error_message = "유저가 존재하지 않습니다." # 사용자 없음 오류 메시지 설정
return render_template("login.html", error_message=error_message) # 로그인 페이지 렌더링
# [2-2. 로그아웃 기능 구현]
@app.route("/logout") # "/logout" 경로에 대한 요청 처리 함수 정의
def logout():
session.pop("user", None) # 세션에서 "user" 정보를 삭제
return redirect(url_for("index")) # 메인 페이지로 리디렉션
# [3. 게시판 페이지 생성]
@app.route("/board") # "/board" 경로에 대한 요청 처리 함수 정의
def view_board():
SQL = """
SELECT id, title, update_date
FROM tb_board
WHERE 1=1
ORDER BY update_date DESC
""" # 게시판 목록을 가져오기 위한 SQL 쿼리
boards = [] # 게시판 목록을 저장할 리스트 초기화
with db_connect() as conn: # 데이터베이스 연결
with conn.cursor() as cur: # 데이터베이스 커서 생성
cur.execute(SQL) # SQL 쿼리 실행
boards = cur.fetchall() # 모든 결과를 가져옴 (여러 게시물)
return render_template("board.html", boards=boards) # 게시판 페이지 렌더링
@app.route("/board/new", methods=["GET"]) # 새 게시물 작성 페이지 요청 (GET 방식)
def view_insert_board():
return render_template("insert_board.html") # 새 게시물 작성 페이지 렌더링
@app.route("/board/new", methods=["POST"]) # 새 게시물 작성 요청 (POST 방식)
def insert_board():
SQL = """
INSERT INTO tb_board(
title, content, user_id
)
VALUES(
%s, %s, %s
)
""" # 새 게시물을 삽입하기 위한 SQL 쿼리
if not session.get('user'): # 로그인 여부 확인
return redirect(url_for("login")) # 로그인 페이지로 리디렉션
user_id = session["user"]["id"] # 세션에서 사용자 ID 가져오기
title = request.form["title"] # 폼에서 입력된 제목 가져오기
content = request.form["content"] # 폼에서 입력된 내용 가져오기
with db_connect() as conn: # 데이터베이스 연결
with conn.cursor() as cur: # 데이터베이스 커서 생성
cur.execute(SQL, [title, content, user_id]) # SQL 쿼리 실행
conn.commit() # 데이터베이스에 변경사항 커밋
return redirect(url_for("view_board")) # 게시판 페이지로 리디렉션
# [4. 게시판 상세 페이지 생성]
@app.route("/board/<int:board_id>") # "/board/<int:board_id>" 경로에 대한 요청 처리 함수 정의 (동적 라우팅)
def view_board_detail(board_id):
SQL = """
SELECT
board.id,
board.title,
board.content,
board.user_id,
user.name,
board.create_date,
board.update_date
FROM tb_board AS board
INNER JOIN tb_user AS user ON board.user_id = user.id
WHERE board.id = %s
""" # 특정 게시물의 상세 정보를 가져오기 위한 SQL 쿼리
board = {} # 게시물 정보를 저장할 딕셔너리 초기화
# [실습 : 댓글도 가져오기]
# 방법1. 여기서 쿼리를 한번 더 실행하여 댓글 가져오기
# 방법2. 별도의 API 라우트를 만들어 fetch()로 댓글 가져오기
with db_connect() as conn: # 데이터베이스 연결
with conn.cursor() as cur: # 데이터베이스 커서 생성
cur.execute(SQL, (board_id,)) # SQL 쿼리 실행
board = cur.fetchone() # 한 개의 게시물 상세 정보 가져오기
return render_template("board_detail.html", board=board) # 게시물 상세 페이지 렌더링
@app.route("/board/update/<int:board_id>", methods=["GET"]) # 게시물 수정 페이지 요청 (GET 방식)
def view_update_board(board_id):
SQL = """
SELECT
id, title, content
FROM
tb_board
WHERE
id = %s
""" # 수정할 게시물 정보를 가져오기 위한 SQL 쿼리
board = {} # 수정할 게시물 정보를 저장할 딕셔너리 초기화
with db_connect() as conn: # 데이터베이스 연결
with conn.cursor() as cur: # 데이터베이스 커서 생성
cur.execute(SQL, (board_id,)) # SQL 쿼리 실행
board = cur.fetchone() # 게시물 정보 가져오기
return render_template("update_board.html", board=board) # 수정 페이지 렌더링
@app.route("/board/update", methods=["POST"]) # 게시물 수정 요청 (POST 방식)
def update_board():
SQL = """
UPDATE tb_board SET
title = %s,
content = %s,
update_date = NOW()
WHERE id = %s
""" # 게시물을 업데이트하기 위한 SQL 쿼리
title = request.form["title"] # 폼에서 입력된 제목 가져오기
content = request.form["content"] # 폼에서 입력된 내용 가져오기
board_id = request.form["board_id"] # 폼에서 입력된 게시물 ID 가져오기
with db_connect() as conn: # 데이터베이스 연결
with conn.cursor() as cur: # 데이터베이스 커서 생성
cur.execute(SQL, [title, content, board_id]) # SQL 쿼리 실행
conn.commit() # 데이터베이스에 변경사항 커밋
return redirect(url_for("view_board_detail", board_id=board_id)) # 수정된 게시물의 상세 페이지로 리디렉션
# [5. 게시판 댓글 추가하기 - API 라우트]
@app.route("/api/comment/<int:board_id>") # "/api/comment/<int:board_id>" 경로에 대한 요청 처리 함수 정의 (동적 라우팅)
def get_board_comments(board_id):
SQL = """
SELECT
user.name, comment.id,
comment.comment, comment.update_date
FROM
tb_board_comment comment
INNER JOIN tb_user user
ON comment.user_id = user.id
WHERE comment.board_id = %s
""" # 특정 게시물의 댓글들을 가져오기 위한 SQL 쿼리
comments = [] # 댓글 목록을 저장할 리스트 초기화
with db_connect() as conn: # 데이터베이스 연결
with conn.cursor() as cur: # 데이터베이스 커서 생성
cur.execute(SQL, (board_id,)) # SQL 쿼리 실행
comments = cur.fetchall() # 모든 댓글을
📘 트러블 슈팅
[문제]
- 문제 내용
출력 과정에서 오류 발생
name = "홍길동" age = 20 print("안녕하세요," + name "님, 당신의 나이는 " + age + "세입니다.")
{ "name": "TypeError", "message": "can only concatenate str (not \"int\") to str", "stack": "--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[2], line 3 1 name = \"홍길동\" 2 age = 20 ----> 3 print(\"안녕하세요,\" + name + \"님, 당신의 나이는 \" + age + \"세입니다.\") TypeError: can only concatenate str (not \"int\") to str" }
- 문제 원인
1종류 이상의 자료형을 한 문장으로 출력하려면; 산술연산자(+)가 아닌 쉼표(,)로 연결
[해결]
- 해결 방법
print("문자열", 변수, "문자열", 변수, "문자열") 의 형태로 출력
- 해결 결과
name = "홍길동" age = 20 print("안녕하세요, ", name, "님, 당신의 나이는 ", age, "세입니다.")
안녕하세요, 홍길동 님, 당신의 나이는 20 세입니다.
📙 내일 일정
- 파이썬 프로그래밍(컨테이너 자료형, 조건문, ...) 학습
'TIL _Today I Learned > 2024.08' 카테고리의 다른 글
[DAY 24] Django 웹 애플리케이션 개발 (0) | 2024.08.13 |
---|---|
[DAY 23] Django 웹 애플리케이션 개발 (0) | 2024.08.12 |
[DAY 21] Flask (0) | 2024.08.08 |
[DAY 20] SQL (0) | 2024.08.07 |
[DAY 19] API, DB, SQL (0) | 2024.08.06 |