[SISS/웹해킹 스터디] 여름 8주차 스터디 - 플라스크
: 8주차 08/19 ~ 08/25 생활코딩 Flask web framework 06 ~ 09
6. 읽기
- 아름다운 코드
- 주소를 통해 변수로 입력된 값 → 기본 문자열 형식이므로
- 코드에서 형변환하거나
- <int:id>와 같은 형식지정자를 사용
- 데이터 읽어오기
- 함수 선언으로 모듈화
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} </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('/create') def create(): return 'create' @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 template(getContents(), f'<h2>{title}</h2>{body}') app.run(debug=True)
- 주소를 통해 변수로 입력된 값 → 기본 문자열 형식이므로
7.1. 쓰기
- CRUD
- Create
- Read
- Update
- Delete
- Create 구현
- template() → <a> 태그 추가
- create() → 입력 태그 추가
- form → 입력 정보를 서버로 전송
- action → 전송 경로
- method → 전송 방식 (값을 변경하므로 post를 이용 / 개발자 도구의 Payload에서 확인 가능)
- (기본) get 메소드
- 서버에 입력 전송 시 url을 통해 전송됨
- 특정 페이지를 식별, 읽어들일 경우에 주로 이용
- (기본) get 메소드
- input → 입력받기
- name → 입력의 이름
- placeholder → 입력 시 보여지는 안내 문구
- textarea → 입력받기(주로 본문)Create 구현
- form → 입력 정보를 서버로 전송
# template에 <a> 추가
def template(contents, content):
...
<ul>
<li><a href="/create">create</a></li>
</ul>
@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)
7.2. 쓰기
- 플라스크 공식 홈페이지 → https://flask.palletsprojects.com/en/3.0.x/
- Routing/HTTP Methods
- get을 이용
- 기본 route 데코레이터
- url 입력
- 링크 클릭
- get을 이용
- Routing/The Request Object
- Routing/Redirects and Errors
- Routing/HTTP Methods
# 공식 안내 - Routing/HTTP Methods
# request 모듈 불러오기
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
# 정보 요청 방법이 post일 경우 실행문
if request.method == 'POST':
return do_the_login()
else:
return show_the_login_form()
# get을 이용
# POST 추가
@app.route('/create', methods=['GET', 'POST'])
# 공식 안내 - Routing/The Request Object
from flask import request
# 메소드 추가
@app.route('/login', methods=['POST', 'GET'])
def login():
error = None
if request.method == 'POST':
if valid_login(request.form['username'],
request.form['password']):
return log_the_user_in(request.form['username'])
else:
error = 'Invalid username/password'
# the code below is executed if the request method
# was GET or the credentials were invalid
return render_template('login.html', error=error)
# 공식 안내 - Routing/Redirects and Errors
from flask import abort, redirect, url_for
@app.route('/')
def index():
# url을 지정하여 로드
return redirect(url_for('login'))
@app.route('/login')
def login():
abort(401)
this_is_never_executed()
# 리디렉션
...
return redirect(url)
8. 수정
- template()
- 기본 아이디 없음 → id=None
- contextUI 변수 추가하여 id 전달받을 경우 update 링크 보여주도록 수정
def template(contents, content, id=None): # 변수 추가 contextUI = '' # id를 받았을 경우 if id != None: contextUI = f''' <li><a href="/update/{id}">update</a></li> ''' return f''' <!doctype html> ... {contextUI} /* contextUI 추가 */ '''
- update()
- 기본 틀은 create()와 동일
- for 문 통해 title과 body를 가져옴 → 수정 시 기존 데이터를 보여주도록 return의 HTML 코드 수정
@app.route('/update/<int:id>', methods=['GET', 'POST']) def update(id): if request.method == 'GET': title = '' body = '' # 수정하려는 정보 가져와 for topic in topics: if id == topic['id']: title = topic['title'] body = topic['body'] break # 보여주기 content = f""" <form action="/update/{id}" method="POST"> <p><input type="text" name="title" placeholder="title" value="{title}"></p> <p><textarea name="body" placeholder="body">{body}</textarea></p> <p><input type="submit" value="update"></p> </form> """ return template(getContents(), content) # 수정 정보 전송 시 elif request.method == 'POST': global nextId title = request.form['title'] body = request.form['body'] for topic in topics: # 아이디로 수정할 데이터 확인 if id == topic['id']: # 정보 수정 topic['title'] = title topic['body'] = body break # 리디렉션 주소 url = '/read/'+str(id) return redirect(url)
9. 삭제
- form
- 페이지로 이동하는 링크(<a>)를 사용할 경우 → 브라우저의 플러그인(페이지를 미리 방문)에 의해 클릭하지 않았음에도 삭제되는 오류가 발생할 수 있음
- GET을 이용한 악의적 삭제를 막기 위해 POST만을 사용
def template(contents, content, id=None): ... if id != None: contextUI = f''' ... <li><form action="/delete/{id}" method="POST"><input type="submit" value="delete"></form></li> '''
- delete
- db에서 데이터 삭제 후 루트로 이동
@app.route('/delete/<int:id>', methods=['POST']) def delete(id): for topic in topics: if id == topic['id']: topics.remove(topic) break return redirect('/')