inflearn logo
강의

Course

Instructor

Building Real-world Websites with Python by Dr. Nam

오류 나는 부분이 있어서 다시 질문 드립니다! 도와주세요! (join 로그인시 백지, 몽고db 이메일주소 null 표시)

Resolved

255

sosgxv9174

24 asked

2

안녕하세요

 

웹개발 입문부분 강좌를 거의다 들었는데.. 오류가 나는 부분이 있어서.. 질문을 올립니다!

 

문제는..join 로그인 하면 몽고db에서 이메일 주소가 null로 표시가 되서.. 동작이 되지 않는점이 있습니다..

 

비슷한 증상을 찾기 어려워서 질문 남깁니다!

 

-화면-

-join-

 

-mongoDB- 

-list-

-list 로그인 페이지-

next_url  << 이게 문제가 나왔었는데 다른 코드들 참고 했는데 해결은 됬습니다.

-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
from flask import session
from functools import wraps
import math

import time
from datetime import datetime, timedelta

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)


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


@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>")
@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("/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 ""
    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")


@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):
    return ""


if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True, port=9000)
 
 
 
 
 
------------------------------------------------------------------------------------------------
 
 
-join-
 
 
{% 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>
 
 
 
----------------------------------------------------------------------------------------------------------
 
-login-
 
{% with messages = get_flashed_messages() %} {% if messages %}
<script>
  alert("{{messages[-1]}}");
</script>
{% endif %} {% endwith %}

<table>
  <form name="form" action="/login" method="POST">
    {% if next_url %}
    <input type="hidden" name="next_url" value="{{next_url}}" />
    {% endif %}
    <thead>
      <caption>
        회원 로그인
      </caption>
    </thead>
    <tbody>
      <tr>
        <td>이메일</td>
        <td><input type="text" name="email" /></td>
      </tr>
      <tr>
        <td>비밀번호</td>
        <td><input type="password" name="pass" /></td>
      </tr>
      <tr>
        <td colspan="2"><input type="submit" value="로그인" /></td>
      </tr>
    </tbody>
  </form>
</table>
 
 
--------------------------------------------------------------------------------------------------------
 
 
- list -
 
 
{% with messages = get_flashed_messages() %}
{% if messages %}
<script>
    alert('{{messages[-1]}}');
</script>
{% endif %}
{% endwith %}

<script>
    function search() {
        var v_search = document.getElementById("search").value;
        var v_keyword = document.getElementById("keyword").value;

        if (v_search == "" || v_keyword == "") {
            return false;
        } else {
            self.location.href =
                "{{url_for('lists')}}?search=" + v_search + "&keyword=" + v_keyword;
        }
    }
</script>

{% if datas|length > 0 %}
<table>
    <thead>
        <tr>
            <td>번호</td>
            <td>제목</td>
            <td>이름</td>
            <td>날짜</td>
            <td>조회수</td>
        </tr>
    </thead>
    <tbody>
        <!--반복되는 구간-->
        <tr>
            {% for data in datas %}
            <td>{{loop.index + ((page - 1) * limit)}}</td>
            <td>
                <a
                    href="{{url_for('board_view', idx=data._id, page=page, search=search, keyword=keyword)}}">{{data.title}}</a>
            </td>
            <td>{{data.name}}</td>
            <td>{{data.pubdate|formatdatetime}}</td>
            <td>{{data.view}}</td>
        </tr>
        {% endfor %}
        <!--반복되는 구간 끝-->
    </tbody>
</table>

{% if block_start - 1 > 0 %}
<a href="{{url_for('lists', page=block_start - 1, search=search, keyword=keyword)}}">[이전]</a>
{% endif %} {% for i in range(block_start, block_last + 1) %} {% if i >
last_page_num %} {{ i }} {% else %} {% if i == page %}
<b>{{ i }}</b>
{% else %}
<a href="{{url_for('lists', page=i, search=search, keyword=keyword)}}">{{ i }}</a>
{% endif %} {% endif %} {% endfor %} {% if block_last < last_page_num %} <a
    href="{{url_for('lists', page=block_last + 1, search=search, keyword=keyword)}}">[다음]</a>
    {% endif %}

    <select name="search" id="search">
        <option value="" {% if search=='' or search==-1 %} selected {% endif %}>검색대상</option>
        <option value="0" {% if search==0 %} selected {% endif %}>제목</option>
        <option value="1" {% if search==1 %} selected {% endif %}>내용</option>
        <option value="2" {% if search==2 %} selected {% endif %}>제목+내용</option>
        <option value="3" {% if search==3 %} selected {% endif %}>작성자</option>
    </select>
    <input type="text" name="keyword" id="keyword" {% if keyword !="" %} value="{{keyword}}" {% endif %} />
    <input type="button" value="검색" onclick="search()" />

    {% else %}
    <h3>데이터가 없습니다.</h3>
    {% endif %}

    <a href="{{url_for('board_write')}}">글작성</a>
 
 
 
-------------------------------------------------------------------------------------------------------
 
 
 
- edit -
 
 
 
<html>

<body>
    <table>
        <form name="form" method="post" action="/edit/{{data._id}}">
            <tr>
                <td>작성자</td>
                <td><input type="text" name="name" value="{{session['name']}}" readonly /></td>
            </tr>
            <tr>
                <td>제목</td>
                <td><input type="text" name="title" /></td>
            </tr>
            <tr>
                <td>내용</td>
                <td><textarea type="text" name="contents">{{data.contents}}</textarea></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" /></td>
            </tr>
        </form>
    </table>
</body>

</html>
 
 
 
 

파이썬 남박사 python 웹사이트 웹개발 사이트만들기 홈페이지

Answer 1

0

nambaksa

그런문제는 프로그램의 흐름을 한번 먼저 생각해보시면 어디에서 문제가 생길지를 미리 예측해볼 수 있습니다.

회원가입을 했는데 이메일값에 문제가 있다면 회원 가입 폼, 회원가입 처리 함수, 이런식으로 프로그램의 흐름을 생각해보며 하나씩 원인을 분석해보는 습관을 들이시는게 좋습니다. 물론 첨부터 쉽지는 않습니다. 어쨌든 그런 순서로 올려주신 코드를 보니,

 

<td><input type="text" nmae="email"></td>

 

 

위와 같이 작성되어있는걸 봤습니다. nmae 이 아니라 name 입니다. 수정해서 한번 다시 해보시기 바랍니다.

 

0

sosgxv9174

남박사님 친절하게 설명해주셔서 감사합니다!! 코드가 많아지니까 오타난거를 찾기가 어렵네요 ㅜ

하다가 모르는거나 궁금한 사항 있으면 질문드리겠습니다~ 감사합니다!

0

nambaksa

원래 제일 찾기 힘든게 오타 입니다. ㅋㅋ

제가 오타를 쉽게 찾은건 그만큼 오타로 고생을 많이 해봐서입니다. 

iis 접속후 자동으로 로그인 창이 나오도록 설정이 기능한가요?

0

64

2

리스트 이동 시 창 에러 발생

0

74

1

배포후 회원 등록 후 로그인 에러...

0

73

2

내부 서버 오류

0

67

2

app.config["MONGO_URI"] = "mongodb://localhost:27017/pm_db"

0

53

2

DB 검색하면 데이터가 없습니다. 라고 나와요. 5시간을 찾아봐도 모르겠어서 문의드려봅니다.

0

44

1

몽고db studio3T를 깔았는데

0

57

2

flake8과 linter

0

72

3

500이 뜹니다.

0

57

2

첨부파일 삭제

0

66

2

검색기능 질문

0

61

2

google.py

0

66

2

Studio 3T에 DB insert가 되지 않는 문제를 해결하지 못하고 있습니다 ㅠ

0

81

3

혹시 전체 코드 공개되어 있나요?

0

96

1

join.html 의 form 태그값 을 member_join() 에서 처리못함.

0

103

1

google.py 몽고db 샘플데이터 만들기

0

99

2

flake8 설치 이후 명령팔레트에서 linter가 안보입니다.

0

236

2

파이썬으로 만들어서 웹호스팅에 올릴경우

0

304

1

현재 구글검색 무한스크롤변경 문의합니다

0

296

1

몽고디비아틀라스로 추가 공부해서 올립니다.

0

217

1

IIS 500.19에러

0

658

2

버전 문제도 수정했는데 결과가 안나옵니다.

0

256

1

데이터베이스 저장관련 질문입니다.

0

269

1

test가 생기지 않습니다.

0

508

3