묻고 답해요
129만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결남박사의 파이썬으로 실전 웹사이트 만들기
글 작성 폼에 HTML 에디터 기능 추가하기 이미지 저장 오류..ㅠ
남박사님 계속 질문해서 죄송합니다..ㅠ 하다보니까 계속 오류가 나네요.... 이미지 업로드 관련해서 ajax 부분에서 오류가 나는것은 영상을 따라 하면서 해봐도 계속 같은 오류가 나와서 답답해서 질문드립니다. - 오류1 - 영상대로 수정하고 적용해서 똑같은 오류가 나오더라구요.. 그래서 이미지 업로드창 눌러서 해봤는데 비슷한 오류가 나옵니다. -오류2- -오류3- - 코드- -write.html- {% extends "main.html" %} {% block contents %} <script> $(document).ready(function() { $("#summernote").summernote({ height: 300, minHeight: null, maxHeight: null, lang: "ko-KR", popover: { image:[], link:[], air:[] }, callbacks: { onImageUpload: function(image) { for(var i = 0; i < image.length; i++) { uploadImage(image[i]); } } } }); }); function uploadImage(image) { var data = new FormData(); data.append("image", image); $.ajax({ url: "{{url_for('board.upload_image')}}", cache: false, contentType: false, processData: false, data: data, type:"post", success: function(url) { var image = $("<img>").attr("src",url).css('max-width', "900px"); $("#summernote").summernote("insertNode",image[0]); }, error: function(data) { console.log(data); alert(data); } }); } </script> <script> function checkForm() { if ($.trim($("#title").val()) == "") { alert("제목을 입력하세요"); $("#title").focus(); return false; } if ($.trim($("#summernote").val()) == "") { alert("내용을 입력하세요"); $("#summernote").focus(); return false; } } </script> <div style="padding: 50px 50px 50px 50px;"> <form name="form" method="post" action="{{url_for('board.board_write')}}" onsubmit="return checkForm()"> <div class="form-group"> <label for="name">작성자</label> <input class="form-control" id="name" type="text" name="name" value="{{session['name']}}" readonly> </div> <div class="form-group"> <label for="title">제목</label> <input class="form-control" type="text" name="title" id="title" placeholder="제목을 입력하세요"/> </div> <div class="form-group"> <label for="contents">내용</label> <textarea rows="8" class="form-control" type="text" name="contents" id="summernote" placeholder="내용을 입력하세요"></textarea> </div> <div class="text-center"><input class="btn btn-primary" type="submit" value="작성하기"></div> </form> </div> {% endblock %} --------------------------------------------------------------------------------------- -viev.html- {% extends "main.html" %} {% block contents %} <div style="padding: 50px 50px 50px 50px;"> <table class="table table-bordered"> <tbody> <tr> <td colspan="2">{{result.title}}</td> </tr> <tr> <td>{{result.name}}</td> <td class="text-right">{{result.pubdate|formatdatetime}}</td> </tr> <tr> <td colspan="2"><div style="min-height: 200px;"></div>{% autoescape false %}{{result.contents}}{% endautoescape %}</td> </tr> </tbody> </table> <a class="btn btn-primary" href="{{url_for('board.lists', page=page, search=search, keyword=keyword)}}">리스트</a> {% if session["id"] == result.writer_id %} <a class="btn btn-danger float-right ml-2" href="{{url_for('board.board_delete', idx=result.id)}}">글삭제</a> <a class="btn btn-warning float-right" href="{{url_for('board.board_edit', idx=result.id)}}">글수정</a> {% endif %} </div> {% endblock %} --------------------------------------------------------------------------------------------------- -main.html- <!DOCTYPE html> <html lang="kr"> <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}}</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous"> <script src="https://code.jquery.com/jquery-3.6.0.min.js" type="text/javascript"></script> <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script> <!-- include summernote css/js --> <link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.css" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.js"></script> <script> function validateEmail(email) { var pattern = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/; return pattern.test(email); } </script> {% with messages = get_flashed_messages() %} {% if messages %} <script> alert('{{messages[-1]}}'); </script> {% endif %} {% endwith %} </head> <body> <div class="containter"> {% include "menu.html" %} {% block contents %} {% endblock %} </div> </body> </html> -------------------------------------------------------------------------------------------------- -board.py- from main import * from flask import Blueprint, send_from_directory from flask import send_from_directory bluerprint = Blueprint("board", __name__, url_prefix="/board") @bluerprint.route("/upload_image", methods=["POST"]) def upload_image(): if request.method == "POST": file = request.files["image"] if file and allowed_file(file.filename): filename = "{}.jpg".format(rand_generator()) savefilepath = os.path.join(app.config["BOARD_IMAGE_PATH"], filename) file.save(savefilepath) return url_for("board.board_images", filename=filename) @bluerprint.route("/images/<filename>") def board_images(filename): return send_from_directory(app.config["BOARD_IMAGE_PATH"], filename) @bluerprint.route("/list") def lists(): # 페이지 값 (값이 없는 경우 기본값는 1) page = request.args.get("page", 1, type=int) # 한페이지당 몇개의 게시물을 출력할지 limit = request.args.get("limit", 5, type=int) search = request.args.get("search", -1, type=int) keyword = request.args.get("keyword", "", type=str) # 최종적으로 완성된 쿼리를 만들 변수 query = {} # 검색어 상태를 추가할 리스트 변수 search_list = [] if search == 0: search_list.append({"title": {"$regex": keyword}}) elif search == 1: search_list.append({"contents": {"$regex": keyword}}) elif search == 2: search_list.append({"title": {"$regex": keyword}}) search_list.append({"contents": {"$regex": keyword}}) elif search == 3: search_list.append({"name": {"$regex": keyword}}) # 검색 대상이 한개라도 존재할 경우 query 변수에 $or 리스트를 쿼리 합니다. if len(search_list) > 0: query = {"$or": search_list} print(query) board = mongo.db.board datas = board.find({}).skip( (page - 1) * limit).limit(limit).sort("pubdate", -1) # 게시물의 총 갯수 tot_count = board.count_documents({}) # 마지막 페이지의 수를 구한다. last_page_num = math.ceil(tot_count / limit) # 페이지 블럭을 5개씩 표기 block_size = 5 # 현재 블럭의 위치 block_num = int((page - 1) / block_size) # 블럭의 시작 위치 block_start = int((block_size * block_num) + 1) # 블럭의 끝 위치 block_last = math.ceil(block_start + (block_size - 1)) return render_template( "list.html", datas=list(datas), limit=limit, page=page, block_start=block_start, block_last=block_last, last_page_num=last_page_num, search=search, keyword=keyword, title="게시판 리스트") @bluerprint.route("/view/<idx>") @login_required def board_view(idx): # idx = request.args.get("idx") if idx is not None: page = request.args.get("page") search = request.args.get("search") keyword = request.args.get("keyword") board = mongo.db.board # data = board.find_one({"_id": ObjectId(idx)}) data = board.find_one_and_update({"_id": ObjectId(idx)}, { "$inc": {"view": 1}}, return_document=True) if data is not None: result = { "id": data.get("_id"), "name": data.get("name"), "title": data.get("title"), "contents": data.get("contents"), "pubdate": data.get("pubdate"), "view": data.get("view"), "writer_id": data.get("writer_id", "") } return render_template( "view.html", result=result, page=page, search=search, keyword=keyword, title="글 상세보기") return abort(404) @bluerprint.route("/write", methods=["GET", "POST"]) def board_write(): if session.get("id") is None: return redirect(url_for("member.member_login")) if request.method == "POST": name = request.form.get("name") title = request.form.get("title") contents = request.form.get("contents") print(name, title, contents) current_utc_time = round(datetime.utcnow().timestamp() * 1000) board = mongo.db.board post = { "name": name, "title": title, "contents": contents, "pubdate": current_utc_time, "writer_id": session.get("id"), "view": 0, } x = board.insert_one(post) print(x.inserted_id) return redirect(url_for("board.board_view", idx=x.inserted_id)) else: return render_template("write.html", title="글 작성") @bluerprint.route("/edit/<idx>", methods=["GET", "POST"]) def board_edit(idx): if request.method == "GET": board = mongo.db.board data = board.find_one({"_id": ObjectId(idx)}) if data is None: flash("해당 게시물이 존재하지 않습니다.") return redirect(url_for("board.lists")) else: if session.get("id") == data.get("writer_id"): return render_template("edit.html", data=data, title="글 수정") else: flash("글 수정 권한이 없습니다.") return redirect(url_for("board.lists")) else: title = request.form.get("title") contains = request.form.get("contents") board = mongo.db.board data = board.find_one({"_id": ObjectId(idx)}) if session.get("id") == data.get("writer_id"): board.update_one({"_id": ObjectId(idx)}, { "$set": { "title": title, "contents": contains, } }) flash("수정 되었습니다.") return redirect(url_for("board.board_view", idx=idx)) else: flash("글 수정 권한이 없습니다.") return redirect(url_for("board.lists")) @bluerprint.route("/delete/<idx>") def board_delete(idx): board = mongo.db.board data = board.find_one({"_id": ObjectId(idx)}) if data.get("writer_id") == session.get("id"): board.delete_one({"_id": ObjectId(idx)}) flash("삭제 되었습니다.") else: flash("삭제 권한이 없습니다.") return redirect(url_for("board.lists")) --------------------------------------------------------------------------------- -__init__.py- from flask import Flask from flask import request from flask import render_template from flask_pymongo import PyMongo from bson.objectid import ObjectId from datetime import datetime, timedelta from flask import abort from flask import redirect from flask import url_for from flask import flash from flask import session import math import time import os app = Flask(__name__) app.config["MONGO_URI"] = "mongodb://localhost:27017/myweb" app.config["SECRET_KEY"] = "abcd" app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(minutes=30) mongo = PyMongo(app) BOARD_IMAGE_PATH = "C:\\python\\images" ALLOWED_EXTENSIONS =set(["txt", "pdf", "png", "jpg", "jpeg", "gif"]) app.config["BOARD_IMAGE_PATH"] = BOARD_IMAGE_PATH app.config["MAX-CONTENT_LENGTH"] = 15 * 1024 * 1024 if not os.path.exists(app.config["BOARD_IMAGE_PATH"]): os.mkdir(app.config["BOARD_IMAGE_PATH"]) # 아래의 파일들에서 main 의 app 에 접근을 해야하니 # 아래 import 위에 app 가 선언되어야 합니다. from .common import login_required, allowed_file, rand_generator from .filter import format_datetime # member, board 에서 login_required, format_datetime 을 사용하니까 # 당연히 member 와 board 가 위의 import 보다 먼저 나와선 안됩니다. from . import member from . import board app.register_blueprint(board.bluerprint) app.register_blueprint(member.bluerprint)
-
해결됨남박사의 파이썬으로 실전 웹사이트 만들기
모듈화 과정에서 pylint 오류가 잔뜩나면서.. 직접 임포트를 하더라도 해결이 안되던데 왜그럴까요?
안녕하세요 남박사님..! 계속 질문 해서 죄송합니다..ㅠ 이번은 모듈화 과정에서 계속 문제가 나서 어떻게 해야할까 해서 질문을 올립니다..! 코드가 아예 먹통이 되는거 같더라구요..! 직접 임포트해서 넣은 common,py / filter.py 는 pylint 내용은 나오더라도 오류는 안나는데.. 다른거는 직접 넣어도 전부 오류가 나오네요..! 다른분들이 올리신 글보고 vscode settings에서 format on save 체크가 되어 있어서 해제 했습니다! 이 부분도 이렇게 추가해서 해봤는데 같았습니다! from main import member from main import board from main.filter import format_datetime from main.common import login_required board.py 코드 부분에서 edit 에 is data in None: <<< None이 빨간줄로 표시가 나오던데 왜그런걸까요? @app.route("/edit/<idx>", methods=["GET", "POST"]) def board_edit(idx): if request.method == "GET": board = mongo.db.board data = board.find_one({"_id": ObjectId(idx)}) if data in None: flash("해당 게시물이 존재하지 않습니다.") return redirect(url_for("lists")) else: if session.get("id") == data.get("writer_id"): return render_template("edit.html", data=data) else: flash("글 수정 권한이 없습니다.") return redirect(url_for("lists")) else: title = request.form.get("title") contains = request.form.get("contents") board = mongo.db.board data = board.find_one({"_id": ObjectId(idx)}) if session.get("id") == data.get("writer_id"): board.update_one({"_id": ObjectId(idx)}, { "$set": { "title": title, "contents": contains, } }) flash("수정 되었습니다.") return redirect(url_for("board_view", idx=idx)) else: flash("글 수정 권한이 없습니다.") return redirect(url_for("lists") - 터미널 오류- -pylint 추가오류- - 코드오류 -1 - 기존 임포트 처럼 전부 넣어도 오류가 나오네요.. flaek8 로 변경해도 똑같습니다..! - 코드오류 -2 - - 코드 오류-3- -코드 내용- - run.py- from main import app if __name__ == "__main__": app.run(host="0.0.0.0", debug=True, port=9000) --------------------------------------------------------------------------------------- - __init__.py - from flask import Flask from flask import request from flask import render_template from flask_pymongo import PyMongo from bson.objectid import ObjectId from datetime import datetime, timedelta from flask import abort from flask import redirect from flask import url_for from flask import flash from flask import session import math import time from . import member from . import board from .filter import format_datetime from .common import login_required app = Flask(__name__) app.config["MONGO_URI"] = "mongodb://localhost:27017/myweb" app.config["SECRET_KEY"] = "abcd" app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(minutes=30) mongo = PyMongo(app) -------------------------------------------------------------------------------------- -board.py- from main import * from flask import Flask from flask import request from flask import render_template from flask_pymongo import PyMongo from bson.objectid import ObjectId from datetime import datetime, timedelta from flask import abort from flask import redirect from flask import url_for from flask import flash from flask import session import math import time @app.route("/list") def lists(): # 페이지 값 (값이 없는 경우 기본값는 1) page = request.args.get("page", 1, type=int) # 한페이지당 몇개의 게시물을 출력할지 limit = request.args.get("limit", 5, type=int) search = request.args.get("search", -1, type=int) keyword = request.args.get("keyword", "", type=str) # 최종적으로 완성된 쿼리를 만들 변수 query = {} # 검색어 상태를 추가할 리스트 변수 search_list = [] if search == 0: search_list.append({"title": {"$regex": keyword}}) elif search == 1: search_list.append({"contents": {"$regex": keyword}}) elif search == 2: search_list.append({"title": {"$regex": keyword}}) search_list.append({"contents": {"$regex": keyword}}) elif search == 3: search_list.append({"name": {"$regex": keyword}}) # 검색 대상이 한개라도 존재할 경우 query 변수에 $or 리스트를 쿼리 합니다. if len(search_list) > 0: query = {"$or": search_list} print(query) board = mongo.db.board datas = board.find({}).skip( (page - 1) * limit).limit(limit).sort("pubdate", -1) # 게시물의 총 갯수 tot_count = board.count_documents({}) # 마지막 페이지의 수를 구한다. last_page_num = math.ceil(tot_count / limit) # 페이지 블럭을 5개씩 표기 block_size = 5 # 현재 블럭의 위치 block_num = int((page - 1) / block_size) # 블럭의 시작 위치 block_start = int((block_size * block_num) + 1) # 블럭의 끝 위치 block_last = math.ceil(block_start + (block_size - 1)) return render_template("list.html", datas=list(datas), limit=limit, page=page, block_start=block_start, block_last=block_last, last_page_num=last_page_num, search=search, keyword=keyword) @app.route("/view/<idx>") @login_required def board_view(idx): # idx = request.args.get("idx") if idx is not None: page = request.args.get("page") search = request.args.get("search") keyword = request.args.get("keyword") board = mongo.db.board # data = board.find_one({"_id": ObjectId(idx)}) data = board.find_one_and_update({"_id": ObjectId(idx)}, { "$inc": {"view": 1}}, return_document=True) if data is not None: result = { "id": data.get("_id"), "name": data.get("name"), "title": data.get("title"), "contents": data.get("contents"), "pubdate": data.get("pubdate"), "view": data.get("view"), "writer_id": data.get("writer_id", "") } return render_template("view.html", result=result, page=page, search=search, keyword=keyword) return abort(404) @app.route("/write", methods=["GET", "POST"]) def board_write(): if session.get("id") is None: return redirect(url_for("member_login")) if request.method == "POST": name = request.form.get("name") title = request.form.get("title") contents = request.form.get("contents") print(name, title, contents) current_utc_time = round(datetime.utcnow().timestamp() * 1000) board = mongo.db.board post = { "name": name, "title": title, "contents": contents, "pubdate": current_utc_time, "writer_id": session.get("id"), "view": 0, } x = board.insert_one(post) print(x.inserted_id) return redirect(url_for("board_view", idx=x.inserted_id)) else: return render_template("write.html") @app.route("/edit/<idx>", methods=["GET", "POST"]) def board_edit(idx): if request.method == "GET": board = mongo.db.board data = board.find_one({"_id": ObjectId(idx)}) if data in None: flash("해당 게시물이 존재하지 않습니다.") return redirect(url_for("lists")) else: if session.get("id") == data.get("writer_id"): return render_template("edit.html", data=data) else: flash("글 수정 권한이 없습니다.") return redirect(url_for("lists")) else: title = request.form.get("title") contains = request.form.get("contents") board = mongo.db.board data = board.find_one({"_id": ObjectId(idx)}) if session.get("id") == data.get("writer_id"): board.update_one({"_id": ObjectId(idx)}, { "$set": { "title": title, "contents": contains, } }) flash("수정 되었습니다.") return redirect(url_for("board_view", idx=idx)) else: flash("글 수정 권한이 없습니다.") return redirect(url_for("lists")) @app.route("/delete/<idx>") def board_delete(idx): board = mongo.db.board data = board.find_one({"_id": ObjectId(idx)}) if data.get("writer_id") == session.get("id"): board.delete_one({"_id": ObjectId(idx)}) flash("삭제 되었습니다.") else: flash("삭제 권한이 없습니다.") return redirect(url_for("lists")) ------------------------------------------------------------------------------------------------------- - member.py - from main import * @app.route("/join", methods=["GET", "POST"]) def member_join(): if request.method == "POST": name = request.form.get("name", type=str) email = request.form.get("email", type=str) pass1 = request.form.get("pass", type=str) pass2 = request.form.get("pass2", type=str) if name == "" or email == "" or pass1 == "" or pass2 == "": flash("입력되지 않은 값이 있습니다.") return render_template("join.html") if pass1 != pass2: flash("비밀번호가 일치하지 않습니다.") return render_template("join.html") members = mongo.db.members cnt = members.count_documents({"email": email}) if cnt > 0: flash("중복된 이메일 주소입니다.") return render_template("join.html") current_utc_time = round(datetime.utcnow().timestamp() * 1000) post = { "name": name, "email": email, "pass": pass1, "joindate": current_utc_time, "logintime": "", "logincount": 0, } members.insert_one(post) return redirect(url_for("member_login")) else: return render_template("join.html") @app.route("/login", methods=["GET", "POST"]) def member_login(): if request.method == "POST": email = request.form.get("email") password = request.form.get("pass") next_url = request.form.get("next_url") members = mongo.db.members data = members.find_one({"email": email}) if data is None: flash("회원 정보가 없습니다.") return redirect(url_for("member_login")) else: if data.get("pass") == password: session["email"] = email session["name"] = data.get("name") session["id"] = str(data.get("_id")) session.permanent = True if next_url is not None: return redirect(next_url) else: return redirect(url_for("lists")) return redirect(url_for("lists")) else: flash("비밀번호가 일치하지 않습니다.") return redirect(url_for("member_login")) return "" else: next_url = request.args.get("next_url", type=str) if next_url is not None: return render_template("login.html", next_url=next_url) else: return render_template("login.html") -------------------------------------------------------------------------------------------------- - common.py- from functools import wraps from main import session, redirect, request, url_for def login_required(f): @wraps(f) def decorated_function(*args, **kwargs): if session.get("id") is None or session.get("id") == "": return redirect(url_for("member_login", next_url=request.url)) return f(*args, **kwargs) return decorated_function ------------------------------------------------------------------------------------------------------- - fliter.py - from main import app, datetime, time @app.template_filter('formatdatetime') def format_datetime(value): if value is None: return "" now_timestamp = time.time() offset = datetime.fromtimestamp( now_timestamp) - datetime.utcfromtimestamp(now_timestamp) value = datetime.fromtimestamp((int(value) / 1000)) + offset return value.strftime('%Y-%m-%d %H:%M:%S')
-
해결됨남박사의 파이썬으로 실전 웹사이트 만들기
회원가입 만들기 오류 문의 (AttributeError: 'Cursor' object has no attribute 'count') 오류
안녕하세요 몇일째 오류랑 씨름하다가 여기까지 왔는데.. 도저희 해결이 안나서 문의 남깁니다. 구글링이나.. 다른분들 오류 해결하시는거 찾아보면서 해도.. 계속오류 나면서 하니까 진도가 너무 늦네요..ㅠ 파이썬으로 실전 웹사이트 만들기 - 회원가입 페이지 만들기 중입니다. -오류내용- -코드- (run.py) from flask import Flask from flask import request from flask import render_template from flask_pymongo import PyMongo from bson.objectid import ObjectId from flask import abort from flask import redirect from flask import url_for from flask import flash import math import time from datetime import datetime app = Flask(__name__) app.config["MONGO_URI"] = "mongodb://localhost:27017/myweb" app.config["SECRET_KEY"] = "abcd" mongo = PyMongo(app) @app.template_filter('formatdatetime') def format_datetime(value): if value is None: return "" now_timestamp = time.time() offset = datetime.fromtimestamp( now_timestamp) - datetime.utcfromtimestamp(now_timestamp) value = datetime.fromtimestamp((int(value) / 1000)) + offset return value.strftime('%Y-%m-%d %H:%M:%S') @app.route("/list") def lists(): # 페이지 값 (값이 없는 경우 기본값는 1) page = request.args.get("page", 1, type=int) # 한페이지당 몇개의 게시물을 출력할지 limit = request.args.get("limit", 5, type=int) search = request.args.get("search", -1, type=int) keyword = request.args.get("keyword", type=str) # 최종적으로 완성된 쿼리를 만들 변수 query = {} # 검색어 상태를 추가할 리스트 변수 search_list = [] if search == 0: search_list.append({"title": {"$regex": keyword}}) elif search == 1: search_list.append({"contents": {"$regex": keyword}}) elif search == 2: search_list.append({"title": {"$regex": keyword}}) search_list.append({"contents": {"$regex": keyword}}) elif search == 3: search_list.append({"name": {"$regex": keyword}}) # 검색 대상이 한개라도 존재할 경우 query 변수에 $or 리스트를 쿼리 합니다. if len(search_list) > 0: query = {"$or": search_list} print(query) board = mongo.db.board datas = board.find({}).skip((page - 1) * limit).limit(limit) # 게시물의 총 갯수 tot_count = board.count_documents({}) # 마지막 페이지의 수를 구한다. last_page_num = math.ceil(tot_count / limit) # 페이지 블럭을 5개씩 표기 block_size = 5 # 현재 블럭의 위치 block_num = int((page - 1) / block_size) # 블럭의 시작 위치 block_start = int((block_size * block_num) + 1) # 블럭의 끝 위치 block_last = math.ceil(block_start + (block_size - 1)) return render_template("list.html", datas=list(datas), limit=limit, page=page, block_start=block_start, block_last=block_last, last_page_num=last_page_num, search=search, keyword=keyword) @ app.route("/view/<idx>") def board_view(idx): # idx = request.args.get("idx") if idx is not None: page = request.args.get("page") search = request.args.get("search") keyword = request.args.get("keyword") board = mongo.db.board data = board.find_one({"_id": ObjectId(idx)}) if data is not None: result = { "id": data.get("_id"), "name": data.get("name"), "title": data.get("title"), "contents": data.get("contents"), "pubdate": data.get("pubdate"), "view": data.get("view") } return render_template("view.html", result=result, page=page, search=search, keyword=keyword) return abort(404) @ app.route("/write", methods=["GET", "POST"]) def board_write(): if request.method == "POST": name = request.form.get("name") title = request.form.get("title") contents = request.form.get("contents") print(name, title, contents) current_utc_time = round(datetime.utcnow().timestamp() * 1000) board = mongo.db.board post = { "name": name, "title": title, "contents": contents, "pubdate": current_utc_time, "view": 0, } x = board.insert_one(post) print(x.inserted_id) return redirect(url_for("board_view", idx=x.inserted_id)) else: return render_template("write.html") @app.route("/join", methods=["GET", "POST"]) def member_join(): if request.method == "POST": name = request.form.get("name", type=str) email = request.form.get("email", type=str) pass1 = request.form.get("pass", type=str) pass2 = request.form.get("pass2", type=str) if name == "" or email == "" or pass1 == "" or pass2 == "": flash("입력되지 않은 값이 있습니다.") return render_template("join.html") if pass1 != pass2: flash("비밀번호가 일치하지 않습니다.") return render_template("join.html") members = mongo.db.members cnt = members.find({"email": email}).count() if cnt > 0: flash("중복된 이메일 주소입니다.") return render_template("join.html") current_utc_time = round(datetime.utcnow().timestamp(*1000)) post = { "name": name, "email": email, "pass": pass1, "joindate": current_utc_time, "logintime": " ", "logincount": 0 } members.insert_one(post) return "" else: return render_template("join.html") if __name__ == "__main__": app.run(host="0.0.0.0", debug=True, port=9000) (join.html) {% with messages = get_flashed_messages() %} {% if messages %} <script> alert('{{messages[-1]}}'); </script> {% endif %} {% endwith %} <table> <form name="form" action="/join" method="POST"> <thead> <caption>회원가입</caption> </thead> <tbody> <tr> <td>이름</td> <td><input type="text" name="name"></td> </tr> <tr> <td>이메일</td> <td><input type="text" nmae="email"></td> </tr> <tr> <td>비밀번호</td> <td><input type="password" name="pass"></td> </tr> <tr> <td>비밀번호 확인</td> <td><input type="password" name="pass2"></td> </tr> <tr> <td colspan="2"><input type="submit" value="가입하기"></td> </tr> </tbody> </form> </table>