본문 바로가기

여러가지/테스트

[실습] Blog

● 구조

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

blog/
├── app.py
├── templates/
│   └── home.html

│   └── post.html

│   └── add_post.html
│   └── edit_post.html
├── requirements.txt

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

● 파일

(파일) requirements.txt

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

Flask
Flask-SQLAlchemy

pytz

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

 

(파일) app.py

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

from flask import Flask, request, redirect, url_for, render_template
from flask_sqlalchemy import SQLAlchemy

# datetime, pytz 날짜/시간 모듈 패키지 불러오기
from datetime import datetime

import pytz

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

# 한국 시간 반환 함수
def get_kst_time():
    utc_now = datetime.utcnow()
    kst_timezone = pytz.timezone('Asia/Seoul')
    kst_time = utc_now.replace(tzinfo=pytz.utc).astimezone(kst_timezone)
    return kst_time

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=get_kst_time)

 

    def __repr__(self):

        return f'<Post {self.name}>'


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

@app.route('/')
def home():

    # 시간 순서대로 정렬하여 불러오기
    posts = Post.query.order_by(Post.date_posted.desc()).all()
    return render_template('home.html', posts=posts)

 

# 각 게시물 별 페이지 불러오기
@app.route('/post/<int:post_id>')
def post(post_id):

    # 존재하지 않을 경우 404 ERROR
    post = Post.query.get_or_404(post_id)
    return render_template('post.html', post=post)

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

@app.route('/edit/<int:post_id>', methods=['GET', 'POST'])
def edit_post(post_id):
    post = Post.query.get_or_404(post_id)
    if request.method == 'POST':

        # 기존 게시물에 브라우저로부터 전송된 form의 값 덮어쓰기
        post.title = request.form['title']
        post.content = request.form['content']
        post.date_posted = get_kst_time()
        db.session.commit()
        return redirect(url_for('home'))
    return render_template('edit_post.html', post=post)

@app.route('/delete/<int:post_id>')
def delete_post(post_id):
    post = Post.query.get_or_404(post_id)

    if post:

        db.session.delete(post)

        db.session.commit()

    return redirect(url_for('home'))

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=1999)

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

 

(파일) home.html

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Blog</title>
</head>
<body>
    <h1>HOME</h1>
    <a href="{{ url_for('add_post') }}">Add New Post</a>
    <ul>
        {% for post in posts %}
        <li>

            # 게시물 제목 클릭하여 각 게시물 접속
            <h2><a href="{{ url_for('post', post_id=post.id) }}">{{ post.title }}</a></h2>
            <p>{{ post.date_posted.strftime('%Y-%m-%d %H:%M:%S') }}</p>

            <a href="{{ url_for('edit_post', post_id=post.id) }}">Edit</a>
            <a href="{{ url_for('delete_post', post_id=post.id) }}">Delete</a>
        </li>
        {% endfor %}
    </ul>
</body>
</html>

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

 

(파일) post.html

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Blog</title>
</head>
<body>
    <header>
        <h1>{{ post.title }}</h1>
    </header>
    <div class="container">
        <p>{{ post.date_posted.strftime('%Y-%m-%d %H:%M:%S') }}</p>
        <div>{{ post.content }}</div>
        <a href="{{ url_for('home') }}">Back to Home</a>
    </div>
</body>
</html>

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

 

(파일) add_post.html

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Blog</title>
</head>
<body>
    <h1>Add New Post</h1>
    <form method="POST" action="{{ url_for('add_post') }}">
        <label for="title">Title:</label>
        <input type="text" id="title" name="title">
        <label for="content">Content:</label>
        <textarea id="content" name="content"></textarea>
        <button type="submit">Add Post</button>
    </form>
    <a href="{{ url_for('home') }}">Back to Home</a>
</body>
</html>

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

 

(파일) edit_post.html

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Blog</title>
</head>
<body>
    <h1>Edit Post</h1>
    <form method="POST" action="{{ url_for('edit_post', post_id=post.id) }}">
        <label for="title">Title:</label>
        <input type="text" id="title" name="title" value="{{ post.title }}">
        <label for="content">Content:</label>
        <textarea id="content" name="content">{{ post.content }}</textarea>
        <button type="submit">Save Changes</button>
    </form>
    <a href="{{ url_for('home') }}">Back to Home</a>
</body>
</html>

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

● 실행

Step1. 선수 작업 진행

[참고] https://uyijune15.tistory.com/222

 

[정리] 선수 작업

1) python3 설치# yum install -y python3 2) 최신 패키지 업데이트# yum -y update# pip install --upgrade pip 3) 필요 패키지 설치# yum -y install gcc# pip3 install gunicorn

uyijune15.tistory.com

 

Step2. 방화벽 설정

# firewalll-cmd --permanent --add-port=1999/tcp

# firewall-cmd --reload

 

Step3. 작업 디렉토리 이동

# cd blog

 

Step4. 필수 패키지 설치

# pip3 install -r requirements.txt

 

Step5. 실행

# gunicorn -w 4 -b 0.0.0.0:1999 app:app

# python app.py

 

 

● 테스트

(브라우저) http://<-IP->:<-PORT->