본문 바로가기

꿀팁!

Flask+restful+SQLAlchemy+flask_jwt_extended공부

외주를 시작하기전 Flask+restx를 공부했는데 시작하니 Flask+restful로 구현을 해야 했고 많은 공부를 했던것 같다.

천재 리승형 동무의 설계덕분에 구조부터 완벽하다.

 

flask를 구동할 main.py를 기준으로 같은 폴더내에 readme, requirements.txt가 있어서 개발을 하기전 readme를 보거나 requirements.txt로 pip install을 진행해 모두 같은 환경을 구축하기 쉽게 만들었다.

 

이제 하위 폴더로 api문서를 만드는 docs폴더, 실제 소스코드 구현인 폴더가 있고

docx에서는 각 클래스 별로 폴더를 만들고 각각의 get, post, put, delete인 .yml문서를 만들어준다.

 

post.yml문서를 대충 적어보면

어떤기능인지 기술
---
tags:
  - 원하는 태그기술
parameters:
  - in: body
    name: id
    type: string
    required: true
  - in: body
    name: pw
    type: string
    required: true
  - in: body
    name: name
    type: string
    required: true
  - in: email
    name: email
    required: true
responses:
  200:
    description: 성공메시지
  400:
    description: 실패메시지

이렇게 적어두면 이문서를 보고 api를 이해하기 더 쉬워지고 원한다면 swagger를 이용해 api문서를 보기좋게 관리할수있다.

 

이제 실제 소스코드 구현 폴더로 가보면 api폴더와 service폴더가 있다. api에선 flask와 rest간의 활동을 구현하고 service폴더에서는 해당 api에서 기능이될 함수를 구현해준다.

 

@swag_from("../../docs/클래스명/post.yml")

해당 데코레이터를 이용해 swagger로 볼수있게해준다.

 

클래스내에 get post put delete patch 등 http method를 구현해준다.

def post(self):
     parser = reqparse.RequestParser()
     parser.add_argument('id', type=str, required=True, help="ID is required")
     args = parser.parse_args()
     id = args['id']

위에처럼 requestparser를 이용해 rest로 넘어오는 json형식에서 "id":"text"인 부분에서 id를 찾아 type은 str형식으로 required가 true로 값이 없을시 ID id required가 리턴된다.

이런식으로 add argument해주면서 다 파싱이 끝나면 args에 파싱한 아이디와 값들을 넣어준다.

파이썬내의 일반변수 id에 파싱한 args['id']값을 넣어주고 동작을 하면된다.

 

이제 이런 동작들은

from ..services.기능명_service import (함수명, 클래스명 등등)

을통해 해당하는 기능의 service파일에다 구현해 import 를통해 접근하면된다.

이후 return값을 보고 동작이 잘 실행됐는지 아니면 에러가 떴는지 등을 처리해준다.

class 기능Result:
    SUCCESS = 0
    INVALID_VALUE = 1

요런식으로 services에 class를 선언해주고 

if(result==기능Result.SUCCESS):

api에서 services의 기능result를 import해와서 다음처럼 비교해주어 가독성을 좋게 하고 result에 맞는 처리를 하면된다. SUCCESS면 성공한 경우의 return 틀리면 틀렸다는 메시지를 return

다 똑같은 형식이다. 입력과 출력은 apis의 파일에서 동작은 services의 파일에서 처리하는것이다.

 

실제기능에서 db를 주로 쓰는데 db관련 라이브러리는 SQLAlchemy를 사용했다. 처음써봤는데 엄청 편해서 쓰기 좋았다.

db명에 맞는 클래스를 따로 만들어줘야 한다.

dbclass.query.filter_by(컬럼명=찾을 문자열의 값).first()

db에서 select를 사용할때는 다음처럼 간편하게 쓸수있다.

acc=DBclass(컬럼명=값[으로 db에 들어갈 값을 채워준다.])
db.session.add(acc)
db.session.commit

데이터를 추가할땐 다음처럼 사용하면된다.

 

acc = dbclass.query.filter_by(id="찾을값").first()
db.session.delete(acc)
db.session.commit

데이터를 삭제할땐 다음처럼 사용하면된다.

 

acc = dbclass.query.filter_by(id="찾을값").first()
acc.컬럼명=바꿀값
db.session.add(acc)
db.session.commit

데이터를 바꿀때는 다음처럼 사용하면 된다.

기능이 끝난뒤에는 처리가 어케됐는지 용도로

class 기능Result:
    SUCCESS = 0
    INVALID_VALUE = 1

요것을 이용해 기능Result.SUCCESS를 return해준다.

 

jwt token을 통해 인증을 하게 된다.

@jwt_required()

api에 다음과 같은 데코레이터가 위에있으면 토큰이 있는사용자만 이용할수있게된다.

 

access_token, refresh_token = create_tokens(account)

요런식으로 토큰을 생성해준다.

@jwt_required(refresh=True)
    def get(self):
        current_user = get_jwt_identity()
        new_access_token = create_access_token(identity=current_user, fresh=False)

refresh토큰은 다음과같이 생성해준다.

 

여기서 나온 토큰값을 header부분에 Authorization을 만들어주고 토큰값 앞에 Bearer문자열을 붙이면 정상적으로 토큰을 사용할수있다.

ex) Bearer 토큰값