본문 바로가기

Python

[Flask] 생활코딩 강의 요약

*이 포스트는 생활코딩 Flask 기초 강의를 듣고 요약한 내용이다

https://www.youtube.com/watch?v=X_n6IZmieV8&list=PLuHgQVnccGMClNOIuT3b3M4YZjxmult2y

 

0. 웹 프레임워크

웹 애플리케이션을 개발하기 위해 사용되는 소프트웨어 프레임워크. 웹 개발마다 공통적으로 필요한 부분이 있는데 이러한 기본 구조와 기능을 제공한다. 개발 언어마다 유명한 웹 프레임워크가 있고, python에는 django, FastAPI, Flask가 있다. 오늘은 이 중 이해하기 쉬운 Flask를 다룬다. 

 

flask 앱을 이용해 웹을 구현해 실행시켰을 때, 브라우저는 python을 읽는 것이 아니다. 브라우저는 html만 해석할 수 있다. 하지만 flask는 브라우저가 해석할 수 있도록 바꾸어 브라우저에 보내는 것이다. 그래서 우리가 단순히 html파일만 만들어 배포한다면 그건 정적인 웹이다. 하지만 flask로는 쓰기, 보기, 지우기, 수정 등 동적인 웹을 구현할 수 있다. 


1. 기본 구조

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'hi'

app.run(port=5001, debug=True)

# debug를 True로 설정하면 디버깅모드로 flask 설정
# 코드를 수정할 때마다 서버를 중단했다가 다시 켜서 확인해야하는 번거로움을 줄일 수 있다
# 실제 서비스에 적용할 때는 디버깅모드를 제외해야한다


플라스크는 기본적으로 5000번 포트에서 실행된다 (브라우저에 localhost:5000을 입력하면 보인다는 뜻). 하지만 이미 주소가 쓰이고 있는 등의 오류가 난다면 app.run(port=5001)과 같이 수정할 수도 있다

 

2. 라우팅

웹 프레임워크에서 가장 중요한 개념. 특정 요청에 어떤 함수로 답할 것인지 설정하는 것. 예를 들어 http://localhost:5001/read/1이라는 요청에 어떤 함수로 어떻게 대응할 것인지를 결정한다.

 

from flask import Flask

app = Flask(__name__)

@app.route('/read/<id>/')
def read(id):
    return f'Read+{id}'  

app.run(port=5001, debug=True)


이제 http://localhost:5001/read/1을 브라우저 주소창에 입력하면 'Read 1'이, http://localhost:5001/read/534를 입력하면 'Read 534'를 브라우저에 띄운다.

 

2. html코드를 활용한 홈페이지 구현

웹에 구현할 내용을 딕셔너리에 정리하고 for문을 통해 웹에 노출해보자.

 

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 ...'}
]

@app.route('/')
def index():
    liTags = ''
    for topic in topics:
        liTags += f'<li>{topic["title"]}</li>'
    return f'''<!doctype html>
    <html>
        <body>
            <h1>WEB</h1>
            <ol>
                {liTags}
            </ol>
        </body>
    </html>
    '''
app.run(port=5001, debug=True)


아래와 같은 결과를 볼 수가 있다. 

* 이 수업에서는 이용하는 데이터로 딕셔너리 형태를 썼지만 실제로는 매번 업데이트된 결과를 반영하고 데이터 양이 많기에 데이터베이스를 이용한다.

 

3. 읽기 기능

정보 시스템의 기본은 네가지. Create, Read, Update, Delete다. 이중 두번째인 Read를 먼저 다뤄보자. 이번에는 위에서 만든 항목에 하이퍼링크를 붙이고 상세페이지의 body를 입력해보자.

 

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 ...'}
]

@app.route('/')
def index():
    liTags = ''
    for topic in topics:
    	# 하이퍼링크를 붙여 id에 해당하는 url로 이동한다
        liTags += f'<li><a href="/read/{topic["id"]}/">{topic["title"]}</a></li>'
    return f'''<!doctype html>
    <html>
        <body>
            <h1>WEB</h1>
            <ol>
                {liTags}
            </ol>
        </body>
    </html>
    '''

# 읽기 페이지
# 각 페이지에서는 각 id에 해당하는 title과 body를 반환한다
@app.route('/read/<int:id>/')
def read(id):
    liTags = ''
    title = ''
    body = ''
    
    for topic in topics:   
        liTags += f'<li><a href="/read/{topic["id"]}/">{topic["title"]}</a></li>'

    for topic in topics:  
        if id == topic['id'] :
            title  = topic['title']
            body = topic['body']

    return f'''<!doctype html>
    <html>
        <body>
            <h1>WEB</h1>
            <ol>
                {liTags}
            </ol>
            <h2>{title}</h2>
            {body}
        </body>
    </html>
    '''

app.run(port=2000, debug=True)


그런데 중복된 코드들이 있다. 이걸 합쳐서 더 간단하게 만들어보자. html 코드로 간단하게 만들어도 되고 여기서는 함수로 해본다.

 

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 templates(content1, content2):
    liTags = ''
    for topic in topics:
        liTags += f'<li><a href="/read/{topic["id"]}/">{topic["title"]}</a></li>'
    return f'''<!doctype html>
    <html>
        <body>
            <h1>WEB</h1>
            <ol>
                {liTags}
            </ol>
            <h2>{content1}</h2>
            {content2}
        </body>
    </html>
    '''

@app.route('/')
def index():
    return templates('', '')

@app.route('/read/<int:id>/')
def read(id):
    title = ''
    body = ''
    
    for topic in topics:  
        if id == topic['id'] :
            title  = topic['title']
            body = topic['body']

    return templates(title, body)

app.run(port=2000, debug=True)

 

4. 쓰기 기능

지금까지 만든 것의 맨마지막에 create 기능을 넣어보자. 기본 템플릿에 create라는 버튼을 하나 추가하고 '/create'로 들어가면 뭔가를 입력할 수 있는 박스를 보여준다.

 

route에 methods 파라메터를 추가할 것이다. methods에는 여러가지가 있지만 여기서는 post 방식, get 방식을 사용한다. 

get은 읽어올 때만 쓰고 post는 새로운 글을 추가하거나 수정할 때 쓰면 된다. /create/은 create 버튼을 누르면 읽어오는 페이지다 그래서 기본적으로 get이다. 그리고 글 추가를 위해 post 기능도 추가되어야 한다.

그리고 새로운 글을 쓰면 페이지에 저장되어 웹페이지에서 볼 수 있어야 한다. 

 

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 templates(content1, content2):
    liTags = ''
    for topic in topics:
        liTags += f'<li><a href="/read/{topic["id"]}/">{topic["title"]}</a></li>'
    return f'''<!doctype html>
    <html>
        <body>
            <h1>WEB</h1>
            <ol>
                {liTags}
            </ol>
            <h2>{content1}</h2>
            {content2}
            	# create 기능 추가
                <li><a href="/create/">create</a></li>
        </body>
    </html>
    '''

@app.route('/')
def index():
    return templates('', '')

@app.route('/read/<int:id>/')
def read(id):
    title = ''
    body = ''
    
    for topic in topics:  
        if id == topic['id'] :
            title  = topic['title']
            body = topic['body']

    return templates(title, body)

# create 페이지
@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 templates('', content)
    
    # 글쓰기 페이지에 글을 입력했을 때
    elif request.method == 'POST':
    	# 여기서 정해지는 글의 id는 글로벌 변수가 된다
        global nextId
        
        # 입력된 정보 불러오기
        title = request.form['title']
        body = request.form['body']
        
        # 데이터에 추가
        newTopic = {'id':nextId, 'title':title, 'body':body}
        topics.append(newTopic)
        
        # 글 입력시 post된 글로 넘어가기
        url = '/read/' +str(nextId) + '/'
        nextId = nextId + 1
        return redirect(url)

app.run(port=2000, debug=True)

 

'Python' 카테고리의 다른 글

[기초] while문 활용해 가위바위보 게임 만들기  (0) 2023.06.26
[기초] Class 생성과 상속  (0) 2023.05.27