24-여름 SISS/웹해킹

[SISS/웹해킹 스터디] 여름 8주차 스터디 - 플라스크

noname64 2024. 8. 20. 23:15

여름 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)
    
    

6. 읽기

 

7.1. 쓰기


  • CRUD
    • Create
    • Read
    • Update
    • Delete

 

  • Create 구현
    • template() → <a> 태그 추가
    • create() → 입력 태그 추가
      • form → 입력 정보를 서버로 전송
        • action → 전송 경로
        • method → 전송 방식 (값을 변경하므로 post를 이용 / 개발자 도구의 Payload에서 확인 가능)
          • (기본) get 메소드
            • 서버에 입력 전송 시 url을 통해 전송됨
            • 특정 페이지를 식별, 읽어들일 경우에 주로 이용
      • input → 입력받기
        • name → 입력의 이름
        • placeholder → 입력 시 보여지는 안내 문구
      • textarea → 입력받기(주로 본문)Create 구현
# 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.1. 쓰기 - 입력 창 생성

 

7.2. 쓰기


    • 플라스크 공식 홈페이지 → https://flask.palletsprojects.com/en/3.0.x/
      • Routing/HTTP Methods
        • get을 이용
          • 기본 route 데코레이터
          • url 입력
          • 링크 클릭
          → form 태그의 POST로 인해 오류가 발생 → 데코레이터 methods 수정 필요 
      •  Routing/The Request Object
      • Routing/Redirects and Errors
더보기

# 공식 안내 - 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)

7.2. 쓰기 - 메소드 오류, flask 입력

 

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)
    

8. 수정 - flask 입력
8. 수정 - chrome으로 수정

 

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('/')
    

9. 삭제 - chrome 삭제