금요일금요일금요일!

금요일금요일금요일!

·

6 min read

오늘 프로젝트 끝났다!

app.py!

from flask import Flask, request, render_template, redirect
import os
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime  # datetime 모듈 추가

basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] =\
    'sqlite:///' + os.path.join(basedir, 'database.db')

db = SQLAlchemy(app)


# db 정보  #

class board(db.Model):   
    id = db.Column(db.Integer, primary_key=True) 
    user = db.Column(db.String, nullable=False)
    title = db.Column(db.String, nullable=False)
    content = db.Column(db.String, nullable=False)
    date = db.Column(db.String, nullable=False)
    category = db.Column(db.String, nullable=False)


class Writing(db.Model):   
    id = db.Column(db.Integer, primary_key=True) 
    board_id = db.Column(db.Integer, db.ForeignKey('board.id', ondelete='CASCADE')) 
    board = db.relationship('board', backref=db.backref('answer_set'))
    category = db.Column(db.String, nullable=False)
    title = db.Column(db.String, nullable=False)
    detail = db.Column(db.String, nullable=False)


class textarea(db.Model):
    id = db.Column(db.Integer, primary_key=True) 
    username = db.Column(db.String, nullable=False)
    comment = db.Column(db.String, nullable=False)
    comment_date = db.Column(db.String, nullable=False)

    def __repr__(self):
        return f'{self.username} {self.comment}'


with app.app_context():
    db.create_all()


# html 불러오기


@app.route("/comment")
def comment():
    return render_template('textarea.html', data=comment)


@app.route("/comment/create")
def comment_create():
    # form에서 보낸 데이터 받아오기
    username_receive = request.args.get("username")
    comment_receive = request.args.get("comment")
    # 이 부분은 입력 안받고 자동설정 가능 할 듯 한데, 혹시 몰라 우선 넣어둘게요!
    comment_date_receive = request.args.get("comment_date")

    # 데이터를 DB에 저장하기
    textarea = textarea(username=username_receive,
                        comment=comment_receive, comment_date=comment_date_receive)
    db.session.add(textarea)
    db.session.commit()
    return redirect(username=username_receive, comment=comment_receive)


@app.route('/write', methods=['GET', 'POST'])
def write():
    if request.method == 'POST':
        if request.form.get('cancel'):  # 취소 버튼이 눌렸을 때
            # 글 내용을 초기화하고 글쓰기 페이지로 리다이렉트
            return redirect('/write')
        else:
            # POST 요청으로부터 데이터를 가져옴
            category = request.form['category']
            title = request.form['title']
            content = request.form['content']
            # 임시로 user 값과 date 값을 추가하고, 실제 환경에서는 적절한 사용자 정보와 날짜를 사용해야 한다.
            user = "임시 사용자"
            date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

            # 데이터베이스에 게시물 추가
            new_post = board(category=category, title=title, content=content, user=user, date=date)  # user와 date 필드 추가
            db.session.add(new_post)
            db.session.commit()

            return redirect('/') # '/'로 리다이렉션

    else:
        # GET 요청인 경우 작성 페이지 렌더링
        return render_template('write.html')


# 보드 메인화면 - 프론트만 연결하기 (메인화면 반환할 때 자유게시판 함께 반환)

@app.route('/', methods=['GET'])
def board_main():
    # 메인 페이지로 접근할때 get 처리 - 자유게시판 카테고리에 속한 게시글을 board.html로 전달
    posts = board.query.filter_by(category='자유게시판').all()
    return render_template('board.html', posts=posts)


# 카테고리별 목록으로 이동 - db 카테고리에 정보, 뉴스, 자유인지 넣어주면 됨 / 프론트 토글로 클릭해서
# 자유게시판
@app.route('/free', methods = ['GET']) 
def free():
    # 자유게시판 카테고리 게시글만 조회 -> board.html으로 전달
    # 자유게시판 카테고리 선택했을 때 해당 카테고리에 속한 게시글만 조회
    # board = Writing.query.get(board_id)
    posts = board.query.filter_by(category='자유게시판').all()
    # db.session.add(posts)
    # db.session.commit()
    return render_template('board.html', posts=posts, category='자유게시판')

# 정보
@app.route('/info', methods = ['GET'])
def info():
    # 정보 카테고리 게시글만 조회 -> board.html으로 전달
    posts = board.query.filter_by(category='정보').all()
    return render_template('board.html', posts=posts, category='정보')


# 뉴스
@app.route('/news', methods = ['GET'])
def news():
    # 뉴스 카테고리 게시글만 조회 -> board.html으로 전달
    posts = board.query.filter_by(category='뉴스').all()
    return render_template('board.html', posts=posts, category='뉴스')



# 글쓰기로 이동
@app.route('/write')
def gowrite():
    # 글쓰기 페이지로 이동
    return render_template('write.html')


# 취소 버튼을 눌렀을 때 글 내용 초기화
@app.route('/cancel')
def cancel():
    return redirect('/write')


if __name__ == '__main__':  
    app.run(debug=True)

white.html 내꺼!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>게시물 작성</title>
    <!-- 부트스트랩 CSS를 추가 -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <!-- 페이지에 적용할 CSS 스타일 설정 -->
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Single+Day&display=swap');

        body {
            background-image: url(https://cdn.pixabay.com/animation/2023/03/28/02/15/02-15-52-868_512.gif);
            background-size: cover;

        font-family: "Single Day",cursive;
        font-weight: 400;
        font-style: normal;
        }
        .container {
            margin: 20px;
            display: flex;
            justify-content: center; /* 수평 가운데 정렬 a*/
            align-items: center; /* 수직 가운데 정렬 */
            height: 90vh; /* 화면 전체 높이를 차지하도록 설정 */
            text-align: justify;
            font-size: 20px; /* 글자 크기 조절 */
        }
        .mini-container {
            border: 1px solid #ccc;
            padding: 20px;
            width: 800px; /* 미니 창의 너비 조정 */
            margin-left: 600px; /* 미니 창의 높이 조정*/
            height: 600px;
            background-image: url(https://plus.unsplash.com/premium_photo-1675695700239-44153e6bf430?q=80&w=1000&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MXx8JUVDJUEyJTg1JUVDJTlEJUI0JTIwJUVDJUE3JTg4JUVBJUIwJTkwfGVufDB8fDB8fHww);
            background-size: cover;
            border:none;
        }
        .text-center {
            position: absolute;
            width: 650px;
            margin-top: 15px;
        }
        .btn-primary {
            background-color:lightpink; /* 부트스트랩의 기본 primary 색상a */
            color: black; /* 버튼 텍스트 색상 */
        }
        .btn-secondary {
            background-color: lightgreen; /* 부트스트랩의 기본 secondary 색상 a*/
            color: black; /* 버튼 텍스트 색상 */
        }
        .btn-close{
            float: right;
            margin-top: -25px;
            background-color: red;
        }
        .navbar {
        width: 85%;
        height: 50px;
        overflow: hidden;
        margin: 17px auto;
        }

        .navbar-brand {
        text-align: center;
        margin: 0 auto;
        font-size: 35px;
        color:  rgb(131, 118, 59);
        }
    </style>
</head>
<body>

<header>
    <nav class="navbar">
        <div class="container-fluid">
          <span class="navbar-brand mb-0 h1">안녕하세요?</span>
        </div>
      </nav>
</header>


<div class="container">
    <div class="mini-container">
        <!-- 글 작성 폼 -->
        <form id="post-form" class="mb-3" action="{{ url_for('write') }}" method="POST">
            <div class="mb-3">
                <!-- 닫기 버튼 -->
                <button type="button" class="btn-close" aria-label="Close"></button>
            </div>
            <div class="mb-3">
                <!-- 카테고리 선택 -->
                <label for="category" class="form-label">카테고리 선택</label>
                <select class="form-select" id="category" name="category">
                    <option value="자유게시판">자유게시판</option>
                    <option value="뉴스">뉴스</option>
                    <option value="정보">정보</option>
                </select>
            </div>
            <div class="mb-3">
                <!-- 제목 입력 -->
                <label for="title" class="form-label">제목:</label>
                <input type="text" class="form-control" id="title" name="title" placeholder="제목을 입력하거라">
            </div>
            <div class="mb-3">
                <!-- 내용 입력 -->
                <label for="content" class="form-label">내용:</label>
                <textarea class="form-control" id="content" name="content" rows="10" placeholder="스위스에서 산새들이 속삭이는 산길 숲속에서 숫사슴을 샅샅이 수색해 식사하고 산속 샘물로 세수하며 사는 삼십삼살 샴쌍둥이 미세스 스미스씨와 미스터 심슨씨는 샘송 설립 사장의 회사 자산 상속자인 사촌의 사돈 김상속씨의 숫기있고 송골송골한 숫색시 샘송 소속 식산업 종사자 김산솜씨를 만나서 샘송 수산물 운송 소속 수색 실장에게 스위스에서 수사슴을 샅샅이 수색했던 것을 인정받아 스위스 수산물 운송 과정에서 상해 삭힌 냄새가 나는 수산물을 수색해내는 샘송 소속 수산물 운송수송 수색 사원이 되기 위해 살신성인으로 쉴새없이 수색했다"></textarea>
            </div>
            <div class="text-center">
                <!-- 작성 버튼 -->
                <button type="submit" class="btn btn-primary btn-lg">작성</button>
                <!-- 취소 버튼 -->
                <button type="button" class="btn btn-secondary btn-lg" onclick="location.href='/cancel';">취소</button>
            </div>
        </form>
    </div>
</div>

<!-- 부트스트랩 JS 추가 -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>

</body>
</html>

board!

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>No Posts</title>
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
      crossorigin="anonymous"
    />

    <script
      src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
      crossorigin="anonymous"
    ></script>
    <style>
      @import url("https://fonts.googleapis.com/css2?family=Single+Day&display=swap");
      body {
        background-image: url(https://cdn.pixabay.com/photo/2017/08/02/14/26/winter-landscape-2571788_1280.jpg);
        background-size: cover;
        font-family: "Single Day", cursive;
        width: 100%;
        height: 100%;
      }
      .single-day-regular {
        font-family: "Single Day", cursive;
        font-weight: 400;
        font-style: normal;
      }
      .navbar {
        width: 100%;
        height: 80px;
        overflow: hidden;
        margin: 17px auto;
      }
      .navbar-brand {
        text-align: center;
        margin: 0 auto;
        font-size: 35px;
        color: rgb(128, 115, 247);
      }
      .category {
        width: 13rem;
        height: 130px;
        margin: 50px 0 0 3%;
      }
      .gesipan {
        /* display: flex; */
        width: 80%;
        height: 100%;
        padding: 20px 0 20px 0;
      }
      .left {
        width: 20%;
        height: 100%;
        padding-left: 20px;
      }
      .btn {
        padding: 22px 70px 22px 70px;
        text-align: center;
        font-size: 22px;
        border-radius: 8px;
        margin: 230px 0 0 3%;
        background-color: lightgoldenrodyellow;
        color: rgb(252, 143, 159);
        border:none;
      }
      /*카테고리 리스트 그룹*/
      .list-group-item {
        padding: 30px 0 30px 0;
      }
      /* .left{
            display: flex;
        } */
      main {
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: row;
      }

      .items {
        padding: 10px;
      }

      p {
        margin: 5px;
      }
      .list-group {
        padding-bottom: 3px;
        width: 80%;
      }
    </style>
  </head>
  <body>
    <header>
      <nav class="navbar">
        <div class="container-fluid">
          <span class="navbar-brand mb-0 h1">게시한 글이 없습니다</span>
        </div>
      </nav>
    </header>
    <main>
      <!--카테고리 - 카테고리 누르면 카테고리별로 이동-->
      <div class="left">
        <div class="category">
          <ul class="list-group list-group-flush">
            <li class="list-group-item" , style="text-align: center; font-size: 20px; background-color: lightgoldenrodyellow;">
              <a href="{{url_for('free')}}">자유게시판</a>
            </li>
            <li class="list-group-item" , style="text-align: center; font-size: 20px; background-color: rgb(208, 250, 237);">
              <a href="{{url_for('info')}}">정보</a>
            </li>
            <li class="list-group-item" , style="text-align: center; font-size: 20px; background-color: whitesmoke;">
              <a href="{{url_for('news')}}">뉴스</a>
            </li>
          </ul>
        </div>
        <!--글쓰기 버튼 - 해당 버튼 누르면 게시글쓰기로 넘어가게-->
        <form action="{{ url_for('write') }}" method="get">
          <button type="submit" class="btn btn-outline-secondary">글쓰기</button>
        </form>
      </div>
      <!--게시글 목록 - 작성된 게시글 내용 뜨게 + 해당 글 누르면 게시물로 넘어감-->
      <div class="gesipan">
        <!-- SVG를 이용한 자유게시판 제목 -->
        <svg width="100%" height="60">
          <defs>
            <linearGradient id="gradient1" x1="0%" y1="0%" x2="100%" y2="0%">
              <stop offset="0%" style="stop-color: red; stop-opacity: 1" />
              <stop offset="20%" style="stop-color: orange; stop-opacity: 1" />
              <stop offset="40%" style="stop-color: yellow; stop-opacity: 1" />
              <stop offset="60%" style="stop-color: green; stop-opacity: 1" />
              <stop offset="80%" style="stop-color: blue; stop-opacity: 1" />
              <stop offset="100%" style="stop-color: purple; stop-opacity: 1" />
            </linearGradient>
          </defs>
          <text fill="url(#gradient1)" font-size="50" x="0%" y="50%" dy=".3em" text-anchor="start">{{category}}</text>
        </svg>
        <ul class="list-group list-group-flush">
          <!-- 이 li 태그를 복사해서 사용하-->
          <li class="list-group items">
            {%for post in posts%}
            <p style="font-size: 30px">{{post.title}}</p>
            <p>{{post.content}}</p>
            <p>작성자: {{post.user}}, 날짜: {{post.date}}</p>
            {%endfor%}
          </li>
        </ul>
        <ul class="list-group list-group-flush">
    </main>
    <footer></footer>
  </body>
</html>

이렇게 일주일의 프로젝트 대장정이 끝이났다!

https://www.youtube.com/watch?v=zLigirpjJ_8&list=LL&index=1