프로젝트/미니 프로젝트

프로젝트 데카르트 4 - 실제 개발 및 테스트

bumm 2024. 4. 8. 16:18

실제 개발된 웹사이트 메인 화면
게시글 작성 화면

 

모든 게시글을 볼 수 있는 페이지
삭제 버튼을 눌렀을 때 나오는 경고 메세지

 


프로젝트 개요

프로젝트 명 : 프로젝트 데카르트(가제)

개발 기간 : 4월 2일 ~ 4월 8일

팀원 및 역할 : 1인 개발

프로젝트 목표 : 철학에 관심있는 일반 대중 또는 교사, 학생들에게 도움이 되는 웹사이트를 만들기 위함

 

사용 기술 및 도구

프로그래밍 언어 및 프레임워크 : Python, HTML, CSS

데이터베이스 : MySQL

라이브러리 및 도구 : Flask

개발환경 : 맥OS, Pycharm

 

기능 목록

구현된 기능 : 기본적인 CRUD의 구현을 목표로 함

기능별 상세 설명 : 게시글을 생성하고 각 게시글을 볼 수 있으며 게시글을 수정 및 삭제할 수 있음

 

개발 과정

2024.04.02. 요구사항 명세서 작성

2024.04.03. 기본적인 프로그램의 UI 예상안 작성

2024.04.06. 본격적인 개발 시작. 게시글 작성 기능과 게시판 기능 추가

2024.04.07. 게시글 수정 기능과 삭제 기능 추가했으나 404 에러로 고치느라 시간을 많이 씀

2024.04.08. 404 에러 수정 시도(실패)

 

테스트 및 검증

테스트 계획 : 게시글 작성이 가능한지, 작성된 게시글이 게시판에 올라가는지, 게시글이 저장되는지, 이 글들이 수정되고 삭제되는지를 테스트할 예정 

테스트 결과 : 작성 및 보기는 가능하지만 수정 및 삭제가 불가능한 상황임.

버그 및 수정 사항 : 수정 및 삭제를 시도하면 404 에러가 발생. 여러 방면으로 코드를 수정했으나 여전히 원인을 찾지 못함.

 

성과 및 피드백

성과 평가 : 프로젝트 목표 달성도 50%(기대했던 기능에 못미침)

피드백 및 개선사항 : 에러를 확인한 후 멘탈을 다잡을 수 있어야 할 듯 함. 정신 수양이 필요해보임. 

 

소스 코드

app.py

from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from flask_wtf.csrf import CSRFProtect
from datetime import datetime

app = Flask(__name__)

# 애플리케이션 설정
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:kmh20938207!@localhost/blog_db'
app.config['SECRET_KEY'] = 'your secret key'
app.config['WTF_CSRF_ENALBLED'] = True

# CSRF 보호 초기화
csrf = CSRFProtect(app)

db = SQLAlchemy(app)

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    content = db.Column(db.Text, nullable=False)
    date_posted = db.Column(db.DateTime, default=datetime.utcnow)

@app.route('/')
def home():
    # 메인 페이지에 게시글 목록을 보여주기 위해 모든 포스트를 조회
    posts = Post.query.order_by(Post.date_posted.desc()).all()
    return render_template('index.html', posts=posts)

@app.route('/create', methods=['GET', 'POST'])
def create_post():
    if request.method == 'POST':
        title = request.form['title']
        content = request.form['content']
        new_post = Post(title=title, content=content)
        db.session.add(new_post)
        db.session.commit()
        return redirect(url_for('home'))
    return render_template('create_post.html')

@app.route('/posts')
def posts():
    posts = Post.query.order_by(Post.date_posted.desc()).all()
    return render_template('posts.html', posts=posts)

if __name__ == '__main__':
    with app.app_context():
        db.create_all()  # 데이터베이스 테이블 생성
    app.run(debug=True)

@app.route('/post/<int:post_id>/delete', methods=['POST'])
def delete_post(post_id):
    post = Post.query.get_or_404(post_id)
    db.session.delete(post)
    db.session.commit()
    return redirect(url_for('posts'))

@app.route('/post/<int:post_id>/edit', methods=['GET', 'POST'])
def edit_post(post_id):
    post = Post.query.get_or_404(post_id)
    if request.method == 'POST':
        post.title = request.form['title']
        post.content = request.form['content']
        db.session.commit()
        return redirect(url_for('posts'))
    return render_template('edit_post.html', post=post)

 

edit_post.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Edit Post</title>
</head>
<body>
    <a href="/post/{{ post.id }}/edit">Edit</a>
    <h1>Edit Post</h1>
    <form action="" method="POST">
        <input type="text" name="title" value="{{ post.title }}" required><br>
        <textarea name="content" required>{{ post.content }}</textarea><br>
        <input type="submit" value="Update">
    </form>
</body>
</html>

 

posts.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>모든 게시글</title>
</head>
<body>
    <h1>모든 게시글</h1>
    <a href="/">Home</a> | <a href="/create">Create Post</a>
    {% for post in posts %}
    <div>
        <h2>{{ post.title }}</h2>
        <p>{{ post.content }}</p>
        <small>Posted on: {{ post.date_posted.strftime('%Y-%m-%d %H:%M') }}</small>
        <form action="/post/{{ post.id }}/delete" method="POST">
            <!-- CSRF 토큰 필드를 이곳에 추가. Flask-WTF를 사용하는 경우 csrf_token() 필요 -->
            <input type="submit" value="Delete" onclick="return confirm('Are you sure?');">
        </form>
        <!-- '수정' 폼의 action URL과 라우트 URL을 정확히 일치시킵니다. method는 'POST'가 아닌 'GET'으로 해야 합니다. -->
        <a href="/post/{{ post.id }}/edit">Edit</a>
    </div>
    {% endfor %}
</body>
</html>

 

create_post.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Create Post</title>
</head>
<body>
    <h1>Create a New Post</h1>
    <form action="/create" method="post">
        <input type="text" name="title" placeholder="Title" required><br>
        <textarea name="content" placeholder="Content" required></textarea><br>
        <button type="submit">Submit</button>
    </form>
</body>
</html>

 

index.html

<!DOCTYPE html>
<html>
<head>
    <style>
        body {
            text-align: center;
        }
    </style>
    <title>철학 명언 씹어먹기 프로젝트</title>
</head>
<body>
    <h1>철학 명언 씹어먹기 프로젝트</h1>
    <p>우리가 일상 속에서 접했던 철학자들의 명언을 씹고 뜯고 맛보는 곳</p>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Main Page</title>
    <style>
        .create-button {
            display: inline-block;
            background-color: #4CAF50; /* Green */
            color: white;
            padding: 10px 20px;
            text-align: center;
            text-decoration: none;
            font-size: 16px;
            margin: 4px 2px;
            cursor: pointer;
            border-radius: 12px;
        }
    </style>
</head>
<body>
    <h1></h1>
    <a href="/create" class="create-button">Create Post</a>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Main Page</title>
    <style>
        .button {
            display: inline-block;
            background-color: #007bff; /* Bootstrap primary blue */
            color: white;
            padding: 10px 20px;
            text-align: center;
            text-decoration: none;
            font-size: 16px;
            margin: 4px 2px;
            cursor: pointer;
            border: none;
            border-radius: 5px;
            transition: all 0.3s ease 0s;
        }

        .button:hover {
            background-color: #0056b3;
            text-decoration: none; /* No underline on hover */
        }
    </style>
</head>
<body>
    <!-- Posts 버튼 추가 -->
    <a href="/posts" class="button">View Posts</a>
    <!-- 게시글 목록 표시 -->
    {% for post in posts %}

    {% endfor %}
</body>
</html>