공부/Flask

[Flask] 간단한 게시판 만들기

래울 2021. 10. 4. 14:00

군대에서 추석연휴간 Flask 공부목적으로 간단한 게시판만들기를 했다.

회원가입, 로그인, 글작성, 글수정, 글삭제 정도..?

flask 체험느낌이라 보안, 디자인등은...ㅇㅅㅇ

 

 

 


 

디렉토리 구조

 

 

login_service : 회원가입/로그인 기능

main : index.py, 메인페이지, 보드, 게시글 관련 기능

 

module : mysql_db

schema : 테이블 정의 등...

 

static : 업로드 이미지, 그외 이미지, js, css 파일 등

templates : 페이지들 .html

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


index.py

#pwd : flask_tutorial/app/main/index.py

from flask import Blueprint, request, render_template, flash, redirect, url_for, session
from flask import current_app as app
from flask import Flask, request
from sqlalchemy import create_engine, text
from app.module import dbModule
from werkzeug.utils import secure_filename
import os
# 추가할 모듈이 있다면 추가
 
main = Blueprint('main', __name__, url_prefix='/')    #index파일을 들어갔을때, 이름을 어떻게 할지, url_prefix는 url을 뒤에 어떻게 붙일지 결정
@main.route('/', methods=['GET'])
def index():
    ## db연결 ##
    db_class = dbModule.Database()    #db연결
    sql = "SELECT * FROM board;" 
    boards = db_class.executeAll(sql)    #[{},{},...,{}] 의 형태
    
    if 'userid' not in session:
        #print("비로그인 상태")
        return render_template('/main/index.html', boards=boards)

    #로그인시, write, delete, update 가능
    #admin은 db자체 편집가능 회원정보, 게시글정보
    #print("로그인 상태")
    userid = session.get('userid', None)
    return render_template('/main/index.html', userid=userid, boards=boards)

@main.route('/write', methods=['GET','POST'])
def write():
    if 'userid' not in session:
        #print("비로그인 상태")
        return "<script>alert(\'로그인 후 이용하세요.\');document.location.href=\"login_service/login\"</script>"
    if request.method == 'GET':
        return render_template('/main/write.html')
    #print("로그인 상태")
    title = request.form['title']
    password = request.form['password']
    contents = request.form['contents']
    if title=='' or password=='' or contents=='':
        return "<script>alert(\'* 은 필수입력입니다.\');document.location.href=\"/write\"</script>"
    
    #파일 업로드
    titleimg = request.files['title_image']
    fn = secure_filename(titleimg.filename) 
    if not fn:    #파일이 없으면
        fn = 'dummy-image.jpg'
    else:
        ######같은 이름 파일 업로드 중복처리.
        _ = 0
        while os.path.isfile("app/static/img/"+fn):
            fn = str(_)+fn
            _ += 1
        titleimg.save(os.path.join('app/static/img/'+ fn))
        
    #print(title,password,contents,request.remote_addr,session.get('userid'))
    db_class = dbModule.Database()    #db연결
    
    userid = session.get('userid')
    sql = "SELECT name from user where id=%s;"
    username = db_class.executeAll(sql, userid)    #username 받아오기
    
    sql = "INSERT INTO board (pwd, name, title, content, ip, viewcnt, titleimg) VALUES (%s, %s, %s, %s, %s, %s, %s);"
    args = (password, username[0]['name'], title, contents, request.remote_addr, 0, fn)
    
    #print(args)
    boards = db_class.executeAll(sql, args)
    db_class.commit()    
    return redirect('/')

@main.route('/board/<int:id>')
def board(id):
    ## db연결 ##
    db_class = dbModule.Database()    #db연결
    sql = "SELECT * FROM board WHERE id=%s;"
    board = db_class.executeAll(sql, id)   #[{},{},...,{}] 의 형태
    if 'userid' not in session:
        #print("비로그인 상태")
        return render_template('/main/board.html', board=board[0])
    
    #print("로그인 상태")
    userid = session.get('userid', None)
    return render_template('/main/board.html', board=board[0], num=id)

    
## 글 수정하기
@main.route('/update', methods=['GET','POST'])
def update():
    if 'userid' not in session:
        #print("비로그인 상태")
        return "<script>alert(\'로그인 후 이용하세요.\');document.location.href=\"login_service/login\"</script>"
    
    #print("로그인 상태")
    db_class = dbModule.Database()    #db연결
    bid = request.args.get('bid')
    if request.method == 'GET':
        if request.args.get('bid')!=None and bid!='':
            sql = "SELECT * FROM board WHERE id=%s;"
            old_board = db_class.executeAll(sql, bid)
            return render_template('/main/update.html', old_board=old_board[0])
    
    # POST
    title = request.form['title']
    contents = request.form['contents']
    password = request.form['password']
    if title=='' or password=='' or contents=='':
        return "<script>alert(\'* 은 필수입력입니다.\');window.history.back();</script>"
    
    sql = "SELECT pwd, titleimg FROM board WHERE id=%s;"
    old_board = db_class.executeAll(sql, bid)
    if old_board[0]['pwd'] != password:
        return "<script>alert(\'비밀번호가 일치하지않습니다.\');window.history.back();</script>"
    
    titleimg = request.files['title_image']    #파일 업로드, 글 수정시 이전파일 삭제 후 업로드
    fn = secure_filename(titleimg.filename) 
    print(old_board, fn, titleimg.filename)
    if old_board[0]['titleimg']!=''and old_board[0]['titleimg']!=None and old_board[0]['titleimg']!='dummy-image.jpg' and fn:    #이미 파일이 있을때 업로드
        os.remove('app/static/img/' + old_board[0]['titleimg'])
        
    ######같은 이름 파일 업로드 중복처리.
    if fn:
        _ = 0
        while os.path.isfile("app/static/img/"+fn):
            fn = str(_)+fn
            _ += 1
        titleimg.save(os.path.join('app/static/img/'+ fn)) 
        sql = "UPDATE board SET title=%s, content=%s, titleimg=%s WHERE id=%s;"
        args = (title, contents, fn, bid)
    else:
        sql = "UPDATE board SET title=%s, content=%s WHERE id=%s;"
        args = (title, contents, bid)
    boards = db_class.executeAll(sql, args)
    db_class.commit()    
    
    sql = "SELECT * FROM board WHERE id=%s;"
    board = db_class.executeAll(sql, bid)
    return render_template('/main/board.html', board=board[0], num=bid)
    
    
#한글파일 이름깨지는 이슈 해결....ㅜㅡㅜ  >> 지원안한다고함;

@main.route('/delete', methods=['GET','POST'])
def delete():
    if 'userid' not in session:
        #print("비로그인 상태")
        return "<script>alert(\'로그인 후 이용하세요.\');document.location.href=\"login_service/login\"</script>"
    
    #print("로그인 상태")
    bid = request.args.get('bid')
    if request.method == 'GET':
        if request.args.get('bid')!=None and bid!='':
            return render_template('/main/delete.html')
    
    db_class = dbModule.Database()    #db연결
    sql = "SELECT pwd FROM board WHERE id=%s;"
    pwd = db_class.executeAll(sql, bid)
    #print(pwd[0]['pwd'], request.form['password'])
    if pwd[0]['pwd'] == request.form['password']:
        sql = "SELECT titleimg FROM board WHERE id=%s;"
        img = db_class.executeAll(sql, bid)[0]['titleimg']
        if img!='dummy-image.jpg' and len(img)!=0:    #이미 파일이 있을때 업로드
            os.remove('app/static/img/' + img)
        sql = "DELETE FROM board WHERE id=%s;"
        db_class.executeAll(sql, bid)
        db_class.commit()   
        return "<script>alert(\'삭제성공\');document.location.href=\"/\"</script>"
    return "<script>alert(\'비밀번호가 일치하지않습니다.\');window.history.back();</script>"
    
####################################### test code start
# code for test.html
@main.route('/test', methods=['GET'])
def test():
    return render_template('/main/test.html')
#
#######################################

 

 

test.py(login_service)

from flask import Blueprint, request, render_template, flash, redirect, url_for, Flask, session
from flask import current_app as current_app
from app.module import dbModule
test = Blueprint('login_service', __name__, url_prefix='/login_service')

@test.route('/register', methods=['GET','POST'])
def register():
    if request.method == 'GET':
        if 'userid' in session:
            session.clear()    #로그인 페이지 진입시, 자동 로그아웃
            return "<script>alert(\'회원가입을 위해 로그아웃합니다.\');document.location.href=\"register\"</script>"
        return render_template('/login_service/register.html')
    uid = request.form['userid']
    uname = request.form['username']
    upw = request.form['password']
    upw2 = request.form['re_password']

    #유효성 검사
    if uid=='' or uname=='' or upw=='' or upw2=='':    #필수입력
        return "<script>alert(\'모두 입력해주세요.\');document.location.href=\"register\"</script>"
    if not upw == upw2:
        return "<script>alert(\'비밀번호 확인이 일치하지않습니다.\');document.location.href=\"register\"</script>"
    
    db_class = dbModule.Database()    #db연결
    sql = "SELECT id FROM user WHERE id=%s;"    #이미 db에 아이디가 존재하는지 검색, 아이디 중복검사
    if db_class.executeAll(sql, uid):           #executeAll함수는 sql과 args를 인자로 받음
        return "<script>alert(\'이미 존재하는 아이디입니다.\');document.location.href=\"register\"</script>"
    sql = "INSERT INTO user VALUES (%s, %s, %s);"
    db_class.executeAll(sql, (uid, upw, uname))
    db_class.commit()                           #commit이 없으면 db에 저장이안됨
    return "<script>alert(\'회원가입이 완료됬습니다.\');document.location.href=\"login\"</script>"    #성공적으로 가입 완료되면, 메시지띄우고, 로그인창으로 이동



# 로그인
@test.route('/login', methods=['GET','POST'])    #GET과 POST메서드 모두 허용
def login():
    if request.method == 'GET':
        if 'userid' in session:
            session.clear()    #로그인 페이지 진입시, 자동 로그아웃
            return "<script>alert(\'로그인페이지로 돌아갑니다.\');document.location.href=\"login\"</script>"
        return render_template('/login_service/login.html')
    uid = request.form['userid']
    upw = request.form['password']
    db_class = dbModule.Database()    #db연결
    sql = "SELECT pwd FROM user WHERE id=%s;"    #해당 아이디의 pwd를 가져옴
    row = db_class.executeAll(sql, uid)
    if row and upw == row[0]['pwd']:    #결과가 하나라도 존재하면, 입력한pw와 비교
        session['userid'] = uid    #세션에 uid를 저장
        return "<script>document.location.href=\'/\';</script>"    #main으로 돌아감 index.html
    return "<script>alert(\'비밀번호가 일치하지않습니다.\');document.location.href=\"login\"</script>"