• 카테고리

    질문 & 답변
  • 세부 분야

    풀스택

  • 해결 여부

    해결됨

(board_edit -> if data in None: 오류)오류나는 부분이 있어서 다시 질문 드립니다!

22.04.11 18:39 작성 조회수 113

2

안녕하세요 남박사님!

 

저번에 질문 올렸는데요!.... 플라스크 프로젝트를 모듈화 하여 패키징 하기 부분에서 오류나서 질문을 드렸었습니다!

죄송합니다만 .... 댓글 달아주셨는데.. 제가 궁금한 부분도 다시 댓글 달았습니다. 답변 부탁드리겠습니다.

 

지금 진도는 javascript, iQuery 폼 검증 기능 추가하기 입니다.

 

모듈화 부분에서 전부 모듈화 하고... venv 들어가 있는 상태에서 재생버튼 눌러서 강제로 실행하니까.. 코드 오류 무시하고 실행이 되더라구요...! 왜그런지는 모르겠습니다!

 

실행이되서 진도를 나갔는데 다른 부분은 전부 정상적으로 적용되는데.. 한곳에서 적용이 안되는 구간이 있어서 질문 올립니다!

 

-코드 오류 -1 -

 

-코드 오류-2 -

 

-글목록 수정-

글목록 작성한다음에 글수정 누르니까 오류가 나옵니다.

-웹페이지 오류-

 

 

-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

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)

# 아래의 파일들에서 main 의 app 에 접근을 해야하니
# 아래 import 위에 app 가 선언되어야 합니다.
from .filter import format_datetime
from .common import login_required

# 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)
 
 
--------------------------------------------------------------------------------------------
 
 
-board.py-
 
 
 
from turtle import title
from main import *
from flask import Blueprint

bluerprint = Blueprint("board", __name__, url_prefix="/board")

@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 in 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"))
 
 
 
 
 
---------------------------------------------------------------------------------
 
 
-member.py-
 
 
from turtle import title
from main import *
from flask import Blueprint

bluerprint = Blueprint("member", __name__, url_prefix="/member")

@bluerprint.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", title="회원가입")
        if pass1 != pass2:
            flash("비밀번호가 일치하지 않습니다.")
            return render_template("join.html", title="회원가입")

        members = mongo.db.members
        cnt = members.count_documents({"email": email})

        if cnt > 0:
            flash("중복된 이메일 주소입니다.")
            return render_template("join.html", title="회원가입")

        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.member_login"))
    else:
        return render_template("join.html", title="회원가입")


@bluerprint.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.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("board.lists"))
                return redirect(url_for("board.lists"))
            else:
                flash("비밀번호가 일치하지 않습니다.")
                return redirect(url_for("member.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, title="회원로그인")
        else:
            return render_template("login.html", title="회원로그인")

@bluerprint.route("/logout")
def member_logout():
    try:
        del session["name"]
        del session["id"]
        del session["email"]
    except:
        pass
    return redirect(url_for('member.member_login'))
 
 
 
----------------------------------------------------------------------------------
 
 
-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>
    {% with messages = get_flashed_messages() %}
        {% if messages %}
            <script>
                alert('{{messages[-1]}}');
            </script>
        {% endif %}
    {% endwith %}
</head>
<body>
    {% include "menu.html" %}
    {% block contents %}
    {% endblock %}
</body>
</html>
 
 
 
---------------------------------------------------------------------------
 
-edit.html-
 
 
 
{% extends "main.html" %}

{% block contents %}

<table>
    <form name="form" method="post" action="{{url_for('board.board_edit', idx=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>

{% endblock %}
 
 
 
-------------------------------------------------------------------------
 
 
 
-join.html-
 
 
 
{% extends "main.html" %}

{% block contents %}

<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" name="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>

{% endblock %}
 
 
 
-------------------------------------------------------------------------------
 
 
 
-list.html-
 
 
 
 
{% extends "main.html" %}

{% block contents %}
<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('board.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.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('board.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('board.lists', page=i, search=search, keyword=keyword)}}">{{ i }}</a>
{% endif %} {% endif %} {% endfor %} {% if block_last < last_page_num %} <a
    href="{{url_for('board.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.board_write')}}">글작성</a>

{% endblock %}
 
 
--------------------------------------------------
 
 
-login.html-
 
 
 
{% extends "main.html" %}

{% block contents %}

<table>
  <form name="form" action="{{url_for('member.member_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>

{% endblock %}
 
 
 
----------------------------------------------
 
-view.html-
 
 
 
{% extends "main.html" %}

{% block contents %}

  {% with messages = get_flashed_messages() %} {% if messages %}
  <script>
    alert("{{messages[-1]}}");
  </script>
  {% endif %} {% endwith %} {{result.title}}
  <br />
  {{result.name}}
  <br />
  {{result.pubdate|formatdatetime}}
  <br />
  {{result.view}}
  <br />
  {{result.contents}}

  <br />
  <a href="{{url_for('board.lists', page=page, search=search, keyword=keyword)}}"
    >리스트</a
  >

  {% if session["id"] == result.writer_id %}
  <a href="{{url_for('board.board_delete', idx=result.id)}}">글삭제</a>
  <a href="{{url_for('board.board_edit', idx=result.id)}}">글수정</a>
  {% endif %}

{% endblock %}
 
 
-------------------------
 
 
-write.html-
 
 
 
 
{% extends "main.html" %}

{% block contents %}

<table>
    <form name="form" method="post" action="{{url_for('board.board_write')}}">
        <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"></textarea></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" /></td>
        </tr>
    </form>
</table>

{% endblock %}
 
 
 
 
 
 

 

답변 1

답변을 작성해보세요.

0

일단 그런 오류가 발생하면 오류의 내용이 복잡해보인다 할지라도 오류의 내용을 자꾸 읽어버릇하는 습관을 들이시는게 좋습니다.

보여주신 오류의 내용을 보면 TypeError 가 발생했고 NoneType 의 아큐먼트가 이터러블하지 않다는 메세지를 발생했으며 해당 코드는 board_edit 의 137라인이라고 나옵니다.

 

if data in None 은 data 가 None 에 있는지를 묻는건데 None 은 그런용도로 사용되는게 아닌걸 아시리라 생각됩니다.  if data is None 이라고 작성하셨어야 할듯 보입니다. 

 

문신호님의 프로필

문신호

질문자

2022.04.12

남박사님 친절한 답변 감사합니다! 말씀해주신거 보니까 제가 잘못 작성한거였네요...ㅠ

수정해보니까 정상동작 합니다!

감사합니다!!