< Python MySQL Connector 셀렉트 하는 방법 >
1) 전체 레시피 가져오는 API를 만들어 보자 우선, 포스트맨을 실행시켜 GET으로 설정하고, URL 입력!
- insert 기능에서 이어서 진행! (참고 : https://sorktjrrb.tistory.com/142)
- 겟(GET)과 딜리트(DELETE) 타입은 바디(Body)를 따로 입력하지 않는다!
- 전체 데이터를 가지고 올때는 offset과 limit를 설정해서 25개씩만 가져오도록 설정하는게 페이지 구성에 좋기 때문에 이를 설정해서 가져오도록 하자
- Params에 offset과 limit라는 키를 생성하고 값은 각각 0, 25로 설정 (URL 에도 추가한 offset 과 limit가 동작되도록 작성해 주어야함 http://127.0.0.1:5000/recipes?offset=0&limit=25 )
# VSCode에서 API 코드 작성!
- recipe.py 파일 안에 레시피를 가져오는(select) 코드문 작성
- 중간 중간 print() 문을 계속 활용해서 디버깅용으로 혹시 문제가 발생되면 print가 실행된 부분까지는 정상 동작이 된것이므로 그 이후를 기준으로 수정하면 된다! 그러므로 pritn()문 계속 중간 검토용으로 사용!
# 우선 코드 작성에 필요한 라이브러리를 import
from flask import request
from flask_restful import Resource
# MySQL DB와 연동하기 위한 라이브러리
from mysql_connection import get_connection
from mysql.connector import Error
# 클래스 생성! 파라미터에는 Resource를 입력해준다. (상속 받기 위해)
class RecipeListResource(Resource) :
# 전체 레시피를 가져오는 API
def get(self) :
# 1. 클라이언트가 보낸 데이터가 있으면 받아준다.
# 하지만 셀렉트문은 따로 클라이언트가 보낼 데이터가 없이 요청에 전체 리스트만 보여주면되므로 작성 필요없음
# postman에서 생성하였던 것처럼 갯수제한을 두기 위해
# request.args를 사용하여 변수를 생성 이것만 해당 부분에 미리 작성
offset = request.args['offset']
limit = request.args['limit']
print(offset, limit)
# 2. DB로부터 데이터를 가져온다.
# 숫자로 지정하는게 아니라 변수로 지정한 offset과 limit를 범위값에 직접 작성 (형태는 정해진 규칙)
# 클라이언트(유저)가 수정하여 보낼 지칭되는 데이터(튜플 형태)가 없으므로 record는 사용하지 않아도됨
try :
connection = get_connection()
query = '''select *
from recipe
limit '''+offset+''', '''+limit+''';'''
# record = () 레코드 필요 없음.
### 중요! select 문은 전체 데이터를 저장된 데이터 형태로 보여주기 때문에 (튜플 형태임 보기가 힘듬)
### 클라이언트(유저)가 좀더 보기 쉬운 딕셔너리 형태로 보여주기 위해서
### dictionary=True를 cursor의 파라미터안에 작성해 준다!
cursor = connection.cursor(dictionary=True)
cursor.execute( query )
### 중요! 쿼리 결과의 모든행을 가져오기 위해.cursor.fetchall() 사용 결과는 리스트로 반환
### 위에서 cursor를 딕셔너리 형태로 생성하였기 때문에 리스트의 각 요소는 딕셔너리 형태로 반환
### 결국 두가지 모두 쿼리 결과를 다루기 쉽고, 읽기 쉬운 형태로 처리하도록 하는것!
result_list = cursor.fetchall()
print(result_list)
cursor.close()
connection.close()
except Error as e :
if cursor is not None:
cursor.close()
if connection is not None:
connection.close()
return {'result' : 'fail', 'errer' : str(e)}, 500
# 3. 클라이언트에 json 만들어서 응답한다. => 문자와 숫자로만 구성하여 보내야 한다.
### 중요! DB에서 가져온 timestamp는 python에서 datetime으로 자동 변환되는데
### 문제는, datetime은 json 형태로 보낼수가 없다! 문자와 숫자로만 구성해야 하기 때문에!
### 따라서, 시간을 문자열로 변환해서 보내주어야 한다.
i = 0
for row in result_list :
result_list[i]['created_at'] = row['created_at'].isoformat()
result_list[i]['updated_at'] = row['updated_at'].isoformat()
i = i + 1
print()
print(result_list)
return {'items' : result_list,
'count' : len(result_list),
'result' : 'success'}
# app.py 파일에 경로와 리소스(API 코드)를 연결하는 코드도 작성!
# API를 처리하는 코드는
# Resource 클래스를 상속받아서 작성한다.
# 이 클래스에는 get, post, put, delete 함수를 상속받는다.
# 따라서 이 함수들을, 우리의 서비스에 맞게 수정해서 사용하면된다.
from flask import Flask
from flask_restful import Api
# 생성한 API class 사용을위해서 생성시마다 import 필요!
from resources.recipe import RecipeListResource
app = Flask(__name__)
api = Api(app)
# 경로(path)와 리소스(API 코드)를 연결한다.
# <int> flask 문법임 외워야됨
api.add_resource( RecipeListResource , '/recipes')
# 완료 되었으면 서버 실행 cmd > flask run 후 postman을 실행하여 send!
# 포스트맨에 200 OK가 뜨고 VScode cmd 창에도 결과가 잘 출력되는것 확인!
2) 레시피를 1개만 가지고 오는 API도 설계해 보자 포스트맨을 실행하여 GET으로 설정하고, URL 입력!
- 주의할점!!! 특정한 데이터를 한가지만 지정하여 가져올때는 당연히 유니크한 값인 id 값이 필요
- ID를 지정하여 가지고 올때는 ID 값을 URL 맨뒤에 /id값 으로 작성하여 가지고 올수 있다.
# VSCode에서 API 코드 작성!
- 상단에 전체레시피를 가져오는 코드에 붙여서 작성
- 우선 형식이 조금 다르므로 새로운 class 생성
class RecipeResource(Resource) :
# 특정 레시피 한개를 가져오는 API
# self, 레시피 db의 id 값 recipe_id
def get(self, recipe_id) :
# 1. 클라이언트로부터 데이터를 받는다.
# print id값 오류가 있을경우 디버깅(수정)위해 입력
print(recipe_id)
# 2. DB로 부터 데이터를 가져온다.
# 위의 recipe_id 에 해당하는 데이터를 가져온다.
try :
connection = get_connection()
# 디버깅 (수정) 과정은 print 문으로 중간 중간 확인 하는것
# 프린트 문이 출력되는 부분까지 문제가 없는거고, print가 실행되지 않는 그 부분이 문제가있는문구인것
print('커넥션 실행')
query = '''select *
from recipe
where id = %s;'''
# 튜플을 단독값으로 넣을땐 , 꼭 추가해줘야 한다! 이런거 기억할것!!!
record = (recipe_id,)
print(record)
# 실행 확인되면 dictionary=True 추가
cursor = connection.cursor(dictionary=True)
print('커서 가져오기 성공')
cursor.execute(query, record)
print('쿼리문 실행')
result_list = cursor.fetchall()
print(result_list)
cursor.close()
connection.close()
except Error as e:
if cursor is not None:
cursor.close()
if connection is not None:
connection.close()
return {'result' : 'fail',
'error' : str(e)}, 500
# 3. 응답할 데이터를 JSON으로 만든다.
i = 0
for row in result_list :
result_list[i]['created_at'] = row['created_at'].isoformat()
result_list[i]['updated_at'] = row['updated_at'].isoformat()
i = i + 1
if len(result_list) == 1 :
return {"item" : result_list[0],
"result" : "success"}
else :
return {"result": "fail",
"error" : "해당 아이디는 존재하지 않습니다."}, 400
# app.py 파일에 경로와 리소스(API 코드)를 연결하는 코드도 작성!
# API를 처리하는 코드는
# Resource 클래스를 상속받아서 작성한다.
# 이 클래스에는 get, post, put, delete 함수를 상속받는다.
# 따라서 이 함수들을, 우리의 서비스에 맞게 수정해서 사용하면된다.
from flask import Flask
from flask_restful import Api
# 생성한 API class 사용을위해서 생성시마다 import 필요!
from resources.recipe import RecipeListResource, RecipeResource
app = Flask(__name__)
api = Api(app)
# 경로(path)와 리소스(API 코드)를 연결한다.
# <int> flask 문법임 외워야됨
# URL에 입력하였던 id 값을 경로로 작성할때는 <int:id 명칭> 형식으로 입력
api.add_resource( RecipeListResource , '/recipes')
api.add_resource( RecipeResource , '/recipes/<int:recipe_id>')
if __name__ == '__main__' :
app.run()
# 확인 및 테스트는 위에서 실행했던 방법과 동일하게 동작해보고 200 OK 확인!
다음 게시글로 계속~!