우선 글을 저장하기 위한 테이블을 mysql에서 만들어줘야 한다.
mysql> CREATE TABLE posts (
-> id INT AUTO_INCREMENT PRIMARY KEY,
-> title VARCHAR(255),
-> content TEXT
-> );
이렇게 만들었었는데 글을 쓴 username도 있어야 한다는 사실을 뒤늦게 깨달아서
ALTER TABLE posts ADD COLUMN username VARCHAR(255);
이걸로 username 속성까지 추가해 주었다.
CRUD 기능을 만들기 전에 먼저
@app.route('/board')
def board():
conn = connectsql()
cursor = conn.cursor(pymysql.cursors.DictCursor)
query = "SELECT id, title, content FROM posts ORDER BY id DESC"
cursor.execute(query)
post = cursor.fetchall()
cursor.close()
conn.close()
return render_template('board.html', post = post)
board 링크에서 글 목록을 볼 수 있게 해주는 페이지를 먼저 만들었다.
id를 기준으로 역순으로 정렬해서 최신 글이 위에 있도록 목록을 만들었다.
post를 board.html 파일로 넘겨주었다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>게시판</title>
</head>
<body>
<h1>게시글 목록</h1>
<ul>
{% for post in post %}
<li><a href="{{ url_for('read', id=post.id) }}">{{ post.title }}</a></li>
{% endfor %}
</ul>
<a href="{{ url_for('write') }}">글 작성</a>
</body>
</html>
board.html 파일에는 글 목록을 클릭해서 read 페이지로 넘어가는 것과 글 작성 링크를 넣어두었다.
<read>
@app.route('/board/read/<id>')
def read(id):
if 'username' in session:
username = session['username']
conn = connectsql()
cursor = conn.cursor(pymysql.cursors.DictCursor)
query = "SELECT id, title, content, username FROM posts WHERE id = %s"
value = id
cursor.execute(query, value)
post = cursor.fetchone()
iswriter = False
if post['username'] == username:
iswriter = True
conn.commit()
cursor.close()
conn.close()
return render_template('read.html', post = post, iswriter = iswriter)
else:
redirect(url_for('login'))
read 링크에서는 mysql 조회를 통해 데이터를 post로 가져온다. 그리고 session에 저장된 username을 이용해
글을 쓴 사람이라면 iswriter를 True로 만들고 read.html에 같이 넘겨준다.
만약 로그인이 안된 상태라면 글을 보지 못하고 login창으로 이동시킨다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ post.title }}</title>
</head>
<body>
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
{% if iswriter %}
<a href="{{ url_for('edit', id=post.id) }}">수정</a>
<a href="{{ url_for('delete', id=post.id) }}" onclick="return confirm('정말 삭제하시겠습니까?');">삭제</a>
{% endif %}
<a href="{{ url_for('board') }}">목록으로</a>
</body>
</html>
read.html에서는 글을 보여주는데 iswriter가 True라면 수정과 삭제 링크가 보이도록 만들었다.
<write>
@app.route('/board/write', methods=['GET', 'POST'])
def write():
if request.method == 'POST':
if 'username' in session:
username = session['username']
title = request.form['title']
content = request.form['content']
conn = connectsql()
cursor = conn.cursor()
query = "INSERT INTO posts (title, content, username) values (%s, %s, %s)"
value = (title, content, username)
cursor.execute(query, value)
conn.commit()
cursor.close()
conn.close()
return redirect('/')
else:
return redirect(url_for('login'))
else:
if 'username' in session:
return render_template ('write.html')
else:
return redirect(url_for('login'))
로그인이 안 되어 있으면 로그인 창으로 이동시킨다.
INSERT 문으로 title, content, username을 posts 테이블에 넣는다.
GET 방식 요청에는 write.html을 렌더링한다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>글 작성</title>
</head>
<body>
<h1>글 작성</h1>
<form method="post" action="/board/write">
<label for="title">제목</label>
<input type="text" id="title" name="title" required>
<br>
<label for="content">내용</label>
<textarea id="content" name="content" required></textarea>
<br>
<button type="submit">작성</button>
</form>
<a href="{{ url_for('index') }}">취소</a>
</body>
</html>
<edit>
@app.route('/board/edit/<id>', methods=['GET', 'POST'])
def edit(id):
if request.method == 'POST':
if 'username' in session:
username = session['username']
edittitle = request.form['title']
editcontent = request.form['content']
conn = connectsql()
cursor = conn.cursor()
query = "UPDATE posts SET title = %s, content = %s WHERE id = %s"
value = (edittitle, editcontent, id)
cursor.execute(query, value)
conn.commit()
cursor.close()
conn.close()
return redirect(url_for('board'))
else:
username = session['username']
conn = connectsql()
cursor = conn.cursor(pymysql.cursors.DictCursor)
query = "SELECT id, title, content FROM posts WHERE id = %s"
value = id
cursor.execute(query, value)
post = cursor.fetchone()
cursor.close()
conn.close()
if username in post:
return render_template('edit.html', post = post)
GET 방식 요청에서는 현재 로그인된 사용자가 게시글의 작성자와 일치하면 edit.html을 렌더링하고
POST 방식 요청에서는 title과 content를 받아서 UPDATE 구문으로 데이터를 업데이트한다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ post.title }} - 수정</title>
</head>
<body>
<h1>{{ post.title }} - 수정</h1>
<form method="post">
<label for="title">제목</label>
<input type="text" id="title" name="title" value="{{ post.title }}" required>
<br>
<label for="content">내용</label>
<textarea id="content" name="content" required>{{ post.content }}</textarea>
<br>
<button type="submit">수정</button>
</form>
<a href="{{ url_for('read', id=post.id) }}">취소</a>
</body>
</html>
edit.html 파일은 write.html 파일과 거의 유사하다.
<delete>
@app.route('/board/delete/<id>')
def delete(id):
if 'username' in session:
username = session['username']
conn = connectsql()
cursor = conn.cursor()
query = "SELECT username FROM posts WHERE id = %s"
value = id
cursor.execute(query, value)
data = [post[0] for post in cursor.fetchall()]
cursor.close()
conn.close()
if username in data:
conn = connectsql()
cursor = conn.cursor()
query = "DELETE FROM posts WHERE id = %s"
value = id
cursor.execute(query, value)
conn.commit()
cursor.close()
conn.close()
return redirect(url_for('board'))
delete 부분은 따로 화면 페이지 이동은 없고 로그인된 사용자가 작성자라면 DELETE 구문으로 데이터를 삭제한다.
'웹개발' 카테고리의 다른 글
게시판(flask)-파일 업로드, 다운로드 (0) | 2023.10.31 |
---|---|
게시판(flask)-댓글, 추천 (0) | 2023.10.31 |
게시판(flask)-회원가입, 로그인, 비밀번호 유효성 검사 (0) | 2023.10.31 |
게시판-비밀번호 유효성 검사, 관리자 글 삭제 권한 기능 추가 (0) | 2023.10.29 |
게시판-파일 업로드, 다운로드 (0) | 2023.10.29 |