* 본 포스팅은 한국품질재단에서 주최하는 인공지능개발자 양성사업 교육과정 복습 용도로 포스팅되었습니다
* Flask : https://flask.palletsprojects.com/en/2.0.x/
Welcome to Flask — Flask Documentation (2.0.x)
flask.palletsprojects.com
- 파이썬으로 작성된 마이크로 웹 프레임워크
- Werkzeug 툴킷과 Jinja2 템플릿 엔진에 기반을 둔다.
* 참고 : Jinja2
https://jinja.palletsprojects.com/en/3.0.x/
Jinja — Jinja Documentation (3.0.x)
jinja.palletsprojects.com
* 기본 예제(형식)
- 로컬PC(localhost)로 웹서비스 제공하는 서버 가동해보기
# 1. 모듈가져오기
from flask import Flask
# 2. 앱생성(플라스크 객체 생성)
app = Flask(__name__)
# 3. 라우팅(사용자가 요청한 페이지의 주소:url을 누가 처리할것인가 연결)
# http : 웹상에서 상호 통신하는 프로토콜
# 127.0.0.1 : 로컬 PC상의 loopback ip 주소 == localhost
# 5000 : 포트, flask의 기본 포트
# http://127.0.0.1:5000 : http 프로토콜 규격에 맞춰서 생성한 url 주소
# URL : http://127.0.0.1:5000/
@app.route('/') # 요청
def home(): # 응답
# 응답처리가 결론
# return => 요청에 대한 응답한다
return '<h1>홈페이지</h1>'
# 4. 웹서비스를 제공하는 서버를 가동
if __name__ == '__main__':
app.run()
* 라우트 추가하여 여러 페이지 만들어보기
- 라우팅 처리를 수행하는 함수의 이름은 고유하다.(중복 X)
- 같은 URL이 중복되게 정의되어 있다면, 먼저 정의된 라우트 함수가 처리된다.
from flask import Flask
app = Flask(__name__)
#http://127.0.0.1:5000/
@app.route('/')
def home():
return '<h1>홈페이지</h1>'
# ~/user/login
@app.route('/users/login')
def login():
return '<h1>로그인페이지</h1>'
# ~/main/service
# 내용은 '<h1>메인 페이지</h1> 이렇게 나오는 웹페이지를 하나 추가하시오
@app.route('/main/service')
def service():
return '<h1>서비스메인페이지</h1>'
if __name__ == '__main__':
# 디버깅 모드를 가동시켜야 소스 수정시
# 브라우저에서 새로고침으로 수정 내용이 반영된다.
app.run(debug=True)
* 클라이언트가 서버 측에 페이지를 요청할 때, 데이터 전달하기
- 로그인, 검색, 게시판 글 상세보기, 게시판 페이지 이동 등
- 데이터를 서버로 보내는 방식
- 메소드(method)방식
- GET 방식 : 가장 일반적이며, 작은 양의 데이터 전송, 보안 취약, 주소 뒤에 ?키=값&키=값
- POST 방식 : 보안에 우수하고, 대량의 데이터 전송, 데이터가 숨겨져 전송
- 동적파라미터 방식
- URL에 실어서 전송, 보안에 취약, 간편하게 사용
* 동적파라미터 방식으로 서버에 데이터 전달하기
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return '<h1>홈페이지2</h1>'
# 동적파라미터 적용 기본
# <news_id> : 여기에 뉴스 아이디를 넣어서 주소창에 넣으면 된다...
# ~/news/9481dknonqnwe
# ~/news/12341246
@app.route('/news/<news_id>')
def news(news_id):
return f'클라이언트가 전달한 데이터 [{news_id}]'
#데이터를 1개 이상 서버 측으로 전달 가능한 가?
# ~/news2/123/제목
@app.route('/news2/<news_id>/<news_title>')
def news2(news_id, news_title):
return f'클라이언트가 전달한 데이터 [{news_id}] [{news_title}]'
# 타입 제한 -> int, float, path
# news_id는 정수값으로만 와야한다.
# 형식을 지키지 않고 요청하면 전부다 404 Not Found(해당 페이지는 없다.) 처리
@app.route('/news3/<int:news_id>')
def news3(news_id):
return f'클라이언트가 전달한 데이터(무조건 정수형태) [{news_id}]'
# path -> 서버측으로 전달할 내용을 무한대로 가변적을 확장할 수 있다.
@app.route('/news4/<path:news_id>')
def news4(news_id):
datas = news_id.split('/')
# 데이터를 추출하고 사용을 리스트의 인덱싱 형식으로 사용
return f'클라이언트가 전달한 데이터(path) [{datas[0]}]'
if __name__ == '__main__':
app.run(debug=True)
* GET방식으로 데이터 전달하기
- 데이터를 전달하지 않아도, 일반적인 모든 페이지는 GET 방식으로 페이지를 요청한다.
- 아무런 표시가 없다면 모두 GET 방식이다.
- 다른 방식으로 (POST, PUT, HEAD, DELETE, ..) 사용한다면 무조건, 명시적으로 표시해야 한다.
- 형식 : 주소(URL) 뒤에 ?키=값&키=값 : 주소형식(모든 웹 프로그래밍 공통)
- 클라이언트가 서버측으로 데이터를 전달할 때 어떤 방식이던 간에 무조건 request 라는 객체를 타고 서버에 전달된다.
from flask import Flask, request
app = Flask(__name__)
# ~/login
# 데이터 전달
# ~/login?uid=guest&name=게스트(클라이언트가 서버한테 준 데이터..)
@app.route('/login')
def login():
# step1 : 클라리언트가 보낸 데이터를 추출
uid = request.args.get('uid')
name = request.args.get('name')
email = request.args.get('email')
print(uid, name, email)
# 만약 클라이언트가 데이터를 보내지 않았다. -> 값 검사 -> 두 개중이라도 한 개라도 값이 없다면
if not uid or not name or not email: # 비정상, 부정상황을 잡는 조건식(uid 가 None이면 False 값 반환, 부정앞 not을 붙혀 긍정만듬. 즉, if 문 실행 -> 코드 짜는 스타일)
#if (uid == None) or (name == None) or (email == None):
return '''
<script>
alert("아이디, 이름, 이메일이 누락되었습니다.")
</script>
'''
else: #정상
return f'<h1>로그인 페이지 {uid} {name}</h1> <p1>이메일 : {email}</p1>'
if __name__ == '__main__':
app.run(debug=True)
* POST방식으로 데이터 전달하기
- 데이터를 숨겨서 서버로 전달
- 보안 우수, 대량의 데이터 전송가능
- API 소개
- render_template('xx.html')
- html을 읽어서 추가된 데이터가 있다면 버무려서 최종 html로 생성하여 응답한다
- 서버 사이드 렌더링을 수행하기 위한 필수조건 -> 템플릿 엔진이 필요
- 템플릿 엔진으로 JinJa를 사용
- html을 해석하고, 데이터를 버무려서 동적으로 다시 html 생성하는 도구
- flask를 설치하면 자동으로 같이 설치된다.
- 해당 서버 소스코드(.py)파일에 같은 위치에 templates 폴더 생성 -> 안에 login.html 파일 생성
<html>
<head>
<!--헤더, 메타 정보 담당-->
</head>
<body>
<!--바디, 화면에 보이는 부분 담당-->
<h2>로그인 페이지</h2>
<fieldset>
<!--사각 테두리-->
<form action='/login' method="POST">
<!--클라이언트에서 서버로 데이터를 전송할 때
데이터를 GET, POST, PUT,... 으로 전달해 주는 역할 담당
=> form 전송 => 브라우저가 껌뻑인다.!(주소창 옆에 X 표시가 잠시 보인다...)
=> 껌뻑인다.=> 화면을 모두 다 다시 렌더링한다... <-> ajax
- 속성
- action : 데이터를 전달할 서버측 주소(URL)
, 만약 생략 시, 현재 페이지가 주소가 된다....
-->
<input type="text" name="uid" placeholder="아이디" required/>
<!--사용자로 부터 입력받는 태그
name 값은 데이터가 서버로 갈 때, 키에 해당된다
placeholder 는 힌트 주는 속성
required 는 입력란이 비어있을 때, 알림 주는 속성-->
<br/>
<br/>
<input type="password" name="upw" placeholder="비밀번호" required/>
<!--사용자로 부터 입력받는 태그
name 값은 데이터가 서버로 갈 때, 키에 해당된다-->
<br/>
<br/>
<input type="submit" value="로그인"/>
<!--사용자로 부터 입력받는 태그-->
</form>
</fieldset>
</body>
</html>
- 클라이언트로 부터 데이터 받아서 출력하기(POST)
from flask import Flask , request, render_template
app = Flask(__name__)
# 현재는 GET만 허용되었다.
# POST까지 허가를 요청한다면 -> 추가 코드 필요...
#@app.route('/login') <- GET 만 허가 된것..
# 1개의 url에서 GET방식과 POST방식을 모두 지원하고 싶다 -> Restful 방식 : url을 최소로 사용..
@app.route('/login', methods=['GET', 'POST']) #GET, POST 모두 허가됨...
def login():
# 분기
if request.method == 'GET': #GET방식으로 들어오면..
return render_template('login.html')
else:
# 전달된 데이터 추출 : 아이디, 비번 추출...
# POST
# 1. 전달된 아이디,비번을 뽑는다.
uid = request.form.get('uid')
upw = request.form.get('upw')
print(uid, upw)
# 2. 아이디, 비번을 가지고 데이터베이스에 쿼리를 수행 (사전에 이미 가입이 되어 있어야 한다...)
# 3. 수행결과를 받는다
# 4. 회원이면 -> 서비스 페이지로 이동
# 5. 회원 아니면 => 아이디 혹은 비번이 틀립니다.. -> 회원가입 유도, 재 로그인 유도
return 'POST 방식으로 데이터가 잘 전달 됨.'
if __name__ == '__main__':
app.run(debug=True)
* 확인하기
- 서버 단 소스코드 실행 후 터미널 확인(http://127.0.0.1:5000)
- 확인 후 주소에 CTRL + 왼쪽 마우스 클릭
- 루프백 주소 뒤 / login 입력하고 접속
- 아이디, 비밀번호 입력 후 로그인 버튼 누른 화면
'Python' 카테고리의 다른 글
[파이썬] Maria DB 연동하기, 웹 로그인 기능 구현하기 (0) | 2021.06.10 |
---|---|
[파이썬] 파이썬 배열의 특징, 슬라이싱, 인덱싱 (0) | 2021.06.03 |
[파이썬] 파이썬, Numpy 사용해보기 (0) | 2021.06.02 |
[파이썬] 파이썬 Pandas 사용해보기 (0) | 2021.06.02 |
파이썬 웹 크롤링으로 데이터 획득하기(파이썬 초보) (0) | 2021.05.31 |