마이크로 프레임워크
__name__
이란?, __name__
이라는 변수는 모듈의 이름이 저장됨__name__
== '__main__'
: 으로 함수 코드를 작성해서 그 함수가 메인이라는 이름을 가질때만 해당 기능을 실험할 수 있음from flask import Flask
# 구분하기 위해 이름을 매겨놓은 것임 __name__ 으로
app = Flask(__name__) # 만들 객체 이름, 일반적으로 프레임워크를 만들떄 사용하는 가이드, 일반적으로 이렇게 만듬 웹서비스
__name__ # 파이썬에서 제공하는 문법
app # 현재 메인이니까 main으로 나옴
- 적절한 목적지를 찾아주는 기능
- URL을 해당 URL 에 맞는 기능과 연결해 줌
- 주소/hello (주소 서버에서 hello 이라는 목적지에 맞는 함수를 호출해 줌)
@app.route("/hello") # 여기 경로로 접속하면 바로밑의 함수를 호출하도록 만들어 놓은 것, 데코레이터
def hello():
return "<h1>Hello World!</h1>"
from flask import Flask
app = Flask(__name__) # 플래스크 객체 생성
@app.route("/hello") # 핼로우라고 접속하면
def test():
return "<h1>Hello Flask!</h1>" # 이 내용이 되도록 웹페이지로 리턴되도록 구성, <h1> 표시가 확대
@app.route('/') # 기본 화면
def main():
return 'main'
host_addr = "0.0.0.0" # 보통 자기 주소 는 0.0.0.0 or localhost or 127.0.0.1
port_num = "8080" # 보통 8080 번을 test로 자주 사용함
if __name__ == "__main__" :
app.run(host=host_addr, port = port_num) # 밑에 주소 뜨면 뭐 404 에러뜸
#왜냐하면 /hello 라는 라우팅 에 만든것이기에 들아가서 /hello 통로로 들어가야뜸
from flask import Flask
app = Flask(__name__)
@app.route("/<username>")
def hello(username):
return f'<h1>안녕 {username}</h1>'
if __name__ == "__main__":
app.run(host="0.0.0.0", port = "8080")
# @app.rount("/meesage/<int:message_id>") # 타입 지정가능 기본형은 문자열
from flask import Flask
app = Flask(__name__)
def add_file(data):
return data + 5
@app.route("/")
def hello():
return '<h1>Hello World!</h1>'
@app.route("/message/<int:message_id>") # message_id를 정수로 받음
def get_message(message_id):
return f"message id: {message_id}"
@app.route("/first/<int:message_id>") # message_id와 함수 매개변수 이름 일치
def get_first(message_id):
data = add_file(message_id) # message_id를 함수로 전달
return f'<h1>{data}</h1>'
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080) # 포트는 정수로 지정
데이터를 가져오기 위해서 http 프로토콜을 쓸때를 RestAPI 라 함
REST(REpresentational State Transfer)
- 자원의 표헨ㅇ 의한 상태 전달
- HTTP URL를 통해 자원을 명시하고, HTTP Method 를 통해 자원에 대한 CRUD Operation 적용
- creat : POST(생성)
- read : GET(조회)
- update : 수정 (PUT)
- delete : 삭제 (DELETE)
REST API- REST 기반으로 서비스 API를 구현한 것
- 마이크로 서비서, Open API 등에서 많이 사용됨
- JSON 타입이 현재 제일 많이 쓰임
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/json_test')
def hello_json():
data = {'name' : '김대리', 'family' : 'Byun'}
return jsonify(data)
@app.route('/server_info')
def server_json():
data = {'server_name' : '0.0.0.0', 'server_port' : '8080'}
return jsonify(data)
if __name__ =='__main__':
app.run(host='0.0.0.0', port =8080)
temlplates 안에 html 파일을 넣음 반환값에 그 파일 이름을 씀
jsonify 딕셔너리형 데이터 집합을 json 형태로 포맷하여 전달
request /주소 값 뒤에 변수들을 받으려고 사용하는 것
method="get" 인 방식은 주소값 뒤에 파라미터 값이 입력되면 파리미터 변수값과 같이 가져옴
터미널 httpie 환경에서 실행된 플라스크에서 파리미터 값을 넣어줄 수있음 그러면 ?물음표를 쓰고 = 를하면 설정 가능 자동으로 역슬래쉬가 생성 될꺼임
?user_name=dave 이런식으로 작성
여러개 넣으려면 ?첫 파라미터=xx&두번째파라미터=xx&세번째파라미터 이런식으로 사용
- html파일은 flask 가 실행되는 하위 폴더인 templates 폴더 안에 위치해야함
- 즉 파이썬에서 앱을 실행 시키고
@app.route('/html_test') # 라우팅 경로 설정
def hello_html():
return redner_template('login.html')
# 하위폴더에 template 안에 있는 longin.html 파일을 찾아서 실행시킨다라고 생각 찾아서 반환 시킨다
# 해당 을 런 시키고 주소창에 해당 라우팅 경로의 주소로 들어가면 template 폴더 안에 있는 login.html 파일을 실행시킨다
# 즉 html 을 라이브로 실행 시킨 것이 아니라 플라스크로 서버를 실행 시킨 것임
@app.route('/login')
def login(): # GET 방식은 뒤에 값이 파라미터 값으로 전달됨 그래서 그냥 주소만 입력하면 user_name 아 아무것도 안들어감
username = request.args.get('user_name') # get방식 사용 하면 주소에 붙어서 나옴
passwd = request.args.get('pw')
email = request.args.get('email_address')
print (username, passwd, email)
if username == 'hak':
return_data = {'auth': 'success'}
else:
return_data = {'auth': 'failed'}
return jsonify(return_data) # 이렇게 보내면 프론트 앤드가 받음
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<form action="/login" method="get">
<p>Enter Name:</p>
<p><input type="text" name="user_name" /></p>
<p><input type="text" name="pw" /></p>
<p><input type="text" name="email_address" /></p>
<p><input type="submit" value="submit" /></p>
</form>
</body>
</html>
처음한것 뒤에 적은것을 그대로 변수로 넣어서 받기 바로 페이지에 띄우기
두번째 한것
동작 순서
작성과정
세번째 지금 배우는것
- 웹페이지에 필요한 부분을 변경할 필요가 있을 때 사용하는 간단한 문법
- 웹페이지에서 파이썬 프로그래밍이 가능
- 문법이므로 세세한 기능이 있지만, 처음 익힐 때는 핵심에 집중
- 다음 두 가지 문법이 핵심
- {{ 변수명 }}
- {% 파이썬 소스코드 %}
- 변수명이나 파이썬 소스코드를 조건이나 변수명을 html 코드로 반환되는 것
- 일종의 프로그래밍 문법임
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/hello/<user>')
def hello_name(user):
return render_template('varable.html', name=user)
@app.route('/hello/<user>')
def hello_name(user):
return render_template('varable.html', name=user,name2=user2,nae2...) # 여러개를 쓰려면 그냥 여러개를 쓰면됨 varable.html 코드에도 사용할 것으 여러개를 적어 놓으면 됨
if __name__=="__main__":
app.run(host="0.0.0.0", port="8080")
{% for %} 로선언하고 {% endfor %} 로 끝남
들여쓰기는 안해도 됨
from flask import Flask, render_template
app =Flask(__name__)
@app.route('/hello_loop')
def hello_name():
value_list = ['list1','list2','list3']
return render_template('loop.html', values=value_list)
<ul> #목차
{% for value in values %}
<li> value </li>
{% endfor %}
</ul>
for i in range(len(values) -> 파이썬
{% for i in range(vlaues | length) %}-> html
<li>{{values[i]}} {{loop.index}}</li> 1 반복 할떄마다 횟수가 1번부터 나옴
{% endfor %}
{% if %} {% elif %} {% else %} {% endif %}
{% if data >= 30 %}
<h3>30보다 큽니다</h3>
{% endif %} # 꼭써야댐
{# #} -> 진자2 템플릿에서의 주석처리
## 실제 프론트엔드(vue)와 flask 기반 RestAPI
> 백엔드는 REST API 를 제공해서 프론트엔드 쪽과 통신하면서 적합한 데이터를 제공해주는 역할을 함
> REST API 기반 기술은 HTTP 프로토콜을 사용해서 requests와 response를 주고받는 형식으로 이루어저 있음
> http 프로토콜에서 요청을 보낼떄 여려가지 method 를 보낼 수 있음
> 4가지 method get, post, put, delete
#### CDN 이란?
* CDN(Contents Delivery Network) 지리적으로 떨어져 있는 사용자에게 컨텐츠 제공자의 컨텐츠를 빠르게 제공할 수 있는 기술을 의미
* 사용자가 멀리 있는 서버로부터 컨텐츠를 받으면 오래 걸리기에 사용자와 가장 가까운 곳에 위치한 Cache Server 에 해당 컨텐츠를 저장해 사용하는 기술
### HTTP 요청 메서드(request method)
* 클라이언트가 서버에 http 요청시 요청 목적을 알리는 표시
* get, post, put, delete 가 있음
* 요청 메서드에 따라 요청 데이터를 전달하는 방식에 차이가 있음
## vue : 익히기 쉬운 기술
> 일종의 웹페이지에서 사용자 인터페이스 또는 웹페이지의 조건이 달라짐에 따라서 해당 웹페이지의 특정 부분만 바로 변경 할 수 있는 기술
> 해당 부분 선택 해당 부분만 update
#### 폴더 구성
* vue 폴더에 flask 폴더 구분
* vue 폴더에 vue_test.html 파일 생성
-
* 관리할 해당 부분 지정 id 로 지정 통상적으로 `<div id="app">` 이렇게 사용한다
```html
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<div>
<h1>Hello, world!</h1>
</div>
<div id="app">
<center>
<button type="button" class="btn btn-primary">GET</button>
<button type="button" class="btn btn-secondary">POST</button>
<button type="button" class="btn btn-success">PUT</button>
<button type="button" class="btn btn-danger">DELETE</button>
</center>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
<!-- Vue Start -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</body>
</html>
v-on:click='axios_test'
를 button html 코드 class 뒤에 넣어준다<script>
const app = new Vue({
el: "#app", // 이부분만 바꿔주면 됨 이름 에 맞게 id 에 적은
methods: {
axios_test() {
axios("http://localhost:8082/test", {
method: "get",
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
},
},
});
</script>
안에 이렇게 놓아줌
data = {'success': True}
jsonify(data)
동일하한 표현임
put과 delete 는 get 방식과 유사하게 동작함
# request 라는 함수를 import 하면 request.method == '' 어떤 메소드인지 확인할 수 있음
# from flask import request
@app.route("/test", methods=['GET', 'POST', 'PUT', 'DELETE']) # 메서드를 제한할 수 있음 설정을 안하면 GET방식만 지원받음
def test():
if request.method == 'POST': # 해당 데이터를 json 형태로 가져와 질 수 있음
print ('POST')
data = request.get_json()
print (data['email'])
if request.method == 'GET':
print ('GET')
user = request.args.get('email')
print (user)
if request.method == 'PUT':
print ('PUT')
user = request.args.get('email')
print (user)
if request.method == 'DELETE':
print ('DELETE')
user = request.args.get('email')
print (user)
return jsonify(
{'status': 'success'}
)
<div id="app">
<br />
<center>
<button type="button" class="btn btn-primary" v-on:click="test_get">
GET
</button>
<button type="button" class="btn btn-secondary" v-on:click="test_post">
POST
</button>
<button type="button" class="btn btn-success" v-on:click="test_put">
PUT
</button>
<button type="button" class="btn btn-danger" v-on:click="test_delete">
DELETE
</button>
</center>
</div>
test_get: () => {
axios("http://localhost:5000/test", {
method: "get",
params: {
email: "test@test.com",
}
})
.then((response) => {
console.log(response.data['status']);
})
.catch((error) => {
console.log(error);
});
},
test_post: () => {
axios("http://localhost:5000/test", {
method: "post",
data: {
email: "test@test.com",
}
})
.then((response) => {
console.log(response.data["status"]);
})
.catch((error) => {
console.log(error);
});
},
test_put: () => {
axios("http://localhost:5000/test", {
method: "put",
params: {
email: "test@test.com",
}
})
.then((response) => {
console.log(response.data["status"]);
})
.catch((error) => {
console.log(error);
});
},
test_delete: () => {
axios("http://localhost:5000/test", {
method: "delete",
params: {
email: "test@test.com",
}
})
.then((response) => {
console.log(response.data["status"]);
})
.catch((error) => {
console.log(error);
});
}
<form method="post" action="input.html">
id: <input tpye="text" name="id"/>
pw: <input type="texT" name="pw"/>
<input type="submit"/>
</form>
"<h3>404 Error 나옴!</h3>
, 404from flask import Flask
import requests
app = Flask(__name__)
@app.errorhandler(404) # 없는 페이지 요청시
def page_not_found(error):
return "<h3>404 Error </h3>", 404
@app.route("/google")
def get_google():
response = requests.get("http://www.google.co.kr")
return response.text
if __name__ == "__main__" :
app.run(host="0.0.0.0", port ="8080")
import logging
# 파일로 남기기 위해서는 filename='test.log' 파라미터, 어느로그 까지남길것인지 level로 설정 가능
logging.basicConfig(filename='test.log', level = logging.ERROR)
# 바로 하면 DEBUG 를 ERROR 로 바꾸면 실행안되고 주피터 노트북을껏다 키면 바뀜
# 로그를 남길 부분에 다음과 같이 로그 레벨에 맞추어 출력해주면 해당 내용이 파일에 들어감
logging.debug("debug") # 제일윗단계라 전체 남겨짐
logging.info("info")
logging.warning("warning")
logging.error("error")
logging.critical("ciritical")
logging 라이브러리와 함꼐 flask logging 사용 가능
logging handler 를 주로 사용함
from flask import Flask
import requests
app = Flask(__name__)
# 2021.12.06 업데이트
# 최근에는 app.debug 값을 app.run 에서 설정하기 전에, 미리 설정해주어야, 하단부 if not app.debug 에 설정이
# 적용되는 것을 확인하였습니다. 따라서, app.debug 값을 미리 설정해주는 코드를 추가하였습니다
# 즉, app.run 에서의 debug 옵션과, app.debug 값을 기반으로 한 logging 설정은 분리된 설정으로 이해하시면 좋을 것 같습니다
app.debug = False
if not app.debug: # 기본적으로 deubg =True 임 상용화에선 False 그래서 확인하려면
import logging
from logging.handlers import RotatingFileHandler # logging 핸들러 이름을 적어줌
file_handler = RotatingFileHandler('dave_server.log', maxBytes=2000, backupCount=10)
file_handler.setLevel(logging.WARNING) # 어느 단계까지 로깅을 할지를 적어줌
app.logger.addHandler(file_handler) # app.logger.addHandler() 에 등록시켜줘야 app.logger 로 사용 가능
@app.errorhandler(404)
def page_not_found(error):
app.logger.error(error)
return "<h1>404 Error</h1>", 404
if __name__ == "__main__":
app.run(host="0.0.0.0", port="8080", dubug=True) # debug False 로하면 if not 저기로 들어가짐
from flask import Flask, request
app = Flask(__name__)
# 첫 번째 요청 여부를 추적하기 위한 전역 변수
initialized = False
# 첫 번째 요청 전에 실행될 함수
def before_first_request():
print("flask 실행 후 첫 요청 때만 실행")
# 모든 요청 전에 실행될 함수
@app.before_request
def before_request(): # 여긴 아직 아무것도 동작하지 않은 상태기에 전달할 내용이 없기에 반환할 것이 없는 것임
global initialized
if not initialized: # 처음 실행된 후에 바뀌기에 다시는 실행되지 않음
before_first_request()
initialized = True
print("HTTP 요청이 들어올 때마다 실행")
# 모든 요청 후에 실행될 함수
@app.after_request
def after_request(response): # 항상 reponse 를 받아야하고
print("HTTP 요청 처리가 끝나고 브라우저에 응답하기 전에 실행")
return response # 반환해줘야함 끝난후에 나오는 거니까 어떤 응답이 왔는지 전달해 줘야 되기에
@app.route("/hello")
def hello():
return "<h1>Hello Flask!</h1>"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)