Flask framework

쓰기 기능 구현

수업소개

쓰기 기능의 구현 방법을 소개합니다. 

 

 

 

강의 1/2

 

 

 

요약

 1. server.py에 아래 코드를 적용해주세요.

from flask import Flask

app = Flask(__name__)


topics = [
    {'id': 1, 'title': 'html', 'body': 'html is ...'},
    {'id': 2, 'title': 'css', 'body': 'css is ...'},
    {'id': 3, 'title': 'javascript', 'body': 'javascript is ...'}
]


def template(contents, content):
    return f'''<!doctype html>
    <html>
        <body>
            <h1><a href="/">WEB</a></h1>
            <ol>
                {contents}
            </ol>
            {content}
            <ul>
                <li><a href="/create/">create</a></li>
            </ul>
        </body>
    </html>
    '''


def getContents():
    liTags = ''
    for topic in topics:
        liTags = liTags + f'<li><a href="/read/{topic["id"]}/">{topic["title"]}</a></li>'
    return liTags


@app.route('/')
def index():
    return template(getContents(), '<h2>Welcome</h2>Hello, WEB')


@app.route('/read/<int:id>/')
def read(id):
    title = ''
    body = ''
    for topic in topics:
        if id == topic['id']:
            title = topic['title']
            body = topic['body']
            break
    return template(getContents(), f'<h2>{title}</h2>{body}')


@app.route('/create/')
def create():
    content = '''
        <form action="/create/" method="POST">
            <p><input type="text" name="title" placeholder="title"></p>
            <p><textarea name="body" placeholder="body"></textarea></p>
            <p><input type="submit" value="create"></p>
        </form>
    '''
    return template(getContents(), content)


app.run(debug=True)

차이점 : https://github.com/egoing/flask-tutorial-src/commit/6798a26010fba21220756c8641691b5727e6f476

 

2. 서버로 전송할 사용자의 입력 정보는 form 태그로 그룹핑 합니다. 

3. <input type="submit"> 버튼은 form 태그 안의 입력 정보를 form의 action 속성으로 method 방식으로 전송합니다. 

4. <form method="XXX"> 가 GET일 때는 브라우저가 서버의 정보를 가져올 때 사용하고, POST는 브라우저가 서버의 정보를 변경할 때 사용합니다.

GET 방식으로 URL을 통해서 입력 정보가 전달 됩니다. 따라서 입력 정보가 노출되고, 길어질 경우 오류가 발생할 수 있습니다. 

POST는 http 통신의 body를 통해서 전송됩니다. 입력 정보가 감춰지고, 대용량의 데이터를 전송 할 수 있습니다. 

 

 

 

강의 2/2

 

 

 

요약 

1. 아래 코드를 server.py에 적용합니다. 

from flask import Flask, request, redirect

app = Flask(__name__)


nextId = 4
topics = [
    {'id': 1, 'title': 'html', 'body': 'html is ...'},
    {'id': 2, 'title': 'css', 'body': 'css is ...'},
    {'id': 3, 'title': 'javascript', 'body': 'javascript is ...'}
]


def template(contents, content):
    return f'''<!doctype html>
    <html>
        <body>
            <h1><a href="/">WEB</a></h1>
            <ol>
                {contents}
            </ol>
            {content}
            <ul>
                <li><a href="/create/">create</a></li>
            </ul>
        </body>
    </html>
    '''


def getContents():
    liTags = ''
    for topic in topics:
        liTags = liTags + f'<li><a href="/read/{topic["id"]}/">{topic["title"]}</a></li>'
    return liTags


@app.route('/')
def index():
    return template(getContents(), '<h2>Welcome</h2>Hello, WEB')


@app.route('/read/<int:id>/')
def read(id):
    title = ''
    body = ''
    for topic in topics:
        if id == topic['id']:
            title = topic['title']
            body = topic['body']
            break
    return template(getContents(), f'<h2>{title}</h2>{body}')


@app.route('/create/', methods=['GET', 'POST'])
def create():
    if request.method == 'GET': 
        content = '''
            <form action="/create/" method="POST">
                <p><input type="text" name="title" placeholder="title"></p>
                <p><textarea name="body" placeholder="body"></textarea></p>
                <p><input type="submit" value="create"></p>
            </form>
        '''
        return template(getContents(), content)
    elif request.method == 'POST':
        global nextId
        title = request.form['title']
        body = request.form['body']
        newTopic = {'id': nextId, 'title': title, 'body': body}
        topics.append(newTopic)
        url = '/read/'+str(nextId)+'/'
        nextId = nextId + 1
        return redirect(url)


app.run(debug=True)

차이점 : https://github.com/egoing/flask-tutorial-src/commit/9f77a029aa0dab6c7251708119383b78d7a90685

 

 2. 브라우저의 요청 정보를 확인하기 위해서는 flask.request 모듈을 이용합니다. 

 

3. request.method는 브라우저가 전송한 method를 확인할 수 있습니다. 

 

4. request.form['NAME'] 는 브라우저가 전송한 POST 데이터를 확인할 수 있습니다. 

 

댓글

댓글 본문
  1. Sansol Park
    지금 작성한 코드는 Flask 웹 애플리케이션으로, 메모리 내에서 데이터를 관리합니다. 즉, 웹 애플리케이션이 실행 중인 동안에만 데이터를 유지하며, 파이썬 서버를 종료하고 다시 실행하면 모든 데이터가 초기화됩니다. 이 때문에 파이썬 서버를 껐다가 다시 켜면 저장된 텍스트가 날아가게 됩니다.

    ### 데이터가 사라지는 이유

    ```python
    topics = [
    {'id': 1, 'title': 'html', 'body': 'html is ...'},
    {'id': 2, 'title': 'css', 'body': 'css is ...'},
    {'id': 3, 'title': 'javascript', 'body': 'javascript is ...'}
    ]
    ```

    위의 코드는 메모리 내에서 `topics` 리스트를 관리합니다. 파이썬 프로그램이 종료되면 메모리에 있는 모든 데이터는 사라지게 됩니다. 따라서 서버를 재시작하면 초기화된 상태로 돌아갑니다.

    ### 데이터를 영구적으로 저장하는 방법

    데이터를 영구적으로 저장하려면 데이터베이스나 파일을 사용해야 합니다. 두 가지 방법을 간단히 설명드리겠습니다.

    1. **파일에 저장하기**:
    - 데이터를 서버의 파일 시스템에 텍스트 파일이나 JSON 파일로 저장하고, 서버가 시작될 때 이 파일을 읽어오도록 하면 데이터를 영구적으로 저장할 수 있습니다.

    2. **데이터베이스 사용하기**:
    - SQLite, MySQL, PostgreSQL과 같은 데이터베이스를 사용하여 데이터를 영구적으로 저장합니다. Flask는 SQLAlchemy 같은 ORM을 통해 데이터베이스와의 상호작용을 쉽게 할 수 있습니다.

    ### 간단한 파일 저장 예시

    여기서는 데이터를 JSON 파일에 저장하는 방법을 간단히 설명합니다.

    #### 데이터 저장 코드 수정

    ```python
    import json
    from flask import Flask, request, redirect

    app = Flask(__name__)

    # JSON 파일에서 데이터를 불러오기
    def load_topics():
    try:
    with open('topics.json', 'r') as f:
    return json.load(f)
    except FileNotFoundError:
    return []

    # JSON 파일에 데이터를 저장하기
    def save_topics():
    with open('topics.json', 'w') as f:
    json.dump(topics, f)

    nextId = 4
    topics = load_topics()

    def template(contents, content):
    return f'''<!doctype html>
    <html>
    <body>
    <h1><a href="/">WEB</a></h1>
    <ol>
    {contents}
    </ol>
    {content}
    <ul>
    <li><a href="/create/">create</a></li>
    </ul>
    </body>
    </html>
    '''

    def getContents():
    liTags = ''
    for topic in topics:
    liTags = liTags + f'<li><a href="/read/{topic["id"]}/">{topic["title"]}</a></li>'
    return liTags

    @app.route('/')
    def index():
    return template(getContents(), '<h2>Welcome</h2>Hello, WEB')

    @app.route('/read/<int:id>/')
    def read(id):
    title = ''
    body = ''
    for topic in topics:
    if id == topic['id']:
    title = topic['title']
    body = topic['body']
    break
    return template(getContents(), f'<h2>{title}</h2>{body}')

    @app.route('/create/', methods=['GET', 'POST'])
    def create():
    global nextId
    if request.method == 'GET':
    content = '''
    <form action="/create/" method="POST">
    <p><input type="text" name="title" placeholder="title"></p>
    <p><textarea name="body" placeholder="body"></textarea></p>
    <p><input type="submit" value="create"></p>
    </form>
    '''
    return template(getContents(), content)
    elif request.method == 'POST':
    title = request.form['title']
    body = request.form['body']
    newTopic = {'id': nextId, 'title': title, 'body': body}
    topics.append(newTopic)
    save_topics() # 새 데이터를 추가한 후에 파일에 저장
    url = '/read/'+str(nextId)+'/'
    nextId = nextId + 1
    return redirect(url)

    app.run(debug=True)
    ```

    ### 주요 수정 사항:
    1. **파일 입출력 추가**: `load_topics`와 `save_topics` 함수를 추가하여 데이터를 JSON 파일에 저장하고 불러옵니다.
    2. **서버가 시작될 때 데이터 로드**: 서버가 시작될 때 `topics` 리스트를 `load_topics` 함수를 통해 파일에서 불러옵니다.
    3. **데이터 추가 시 파일에 저장**: 새로운 토픽을 추가할 때마다 `save_topics` 함수를 호출하여 데이터를 파일에 저장합니다.

    이렇게 하면 서버를 재시작해도 JSON 파일에 저장된 데이터를 불러와 사용할 수 있습니다. 데이터베이스를 사용하면 더 강력하고 복잡한 데이터 관리를 할 수 있지만, 이 방법은 간단한 예제에 적합합니다.
    대화보기
    • 드가자
      리스트에 추가된 제목과 본문은 어디에 저장되는건가요? 파이썬을 껏다 켜면 저장된 텍스트는 날아가버리네요
    • 루미꼬짱
      감사합니다.
    • 헤밍웨이
      어렵지만 하나하나 알아가는 재미가 있습니다 :)
    • Lithium3
      코드 바꿔가면서도 하는게 재밌습니다.
    graphittie 자세히 보기