#5. Python์ผ๋ก API ๊ฐ๋ฐ(๊ธฐ๋ณธํ๊ฒฝ๊ตฌ์ฑ)
Python Flask์ ๊ธฐ๋ณธํ๊ฒฝ์ด ๊ตฌ์ฑ๋์๊ณ , ์ด์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ด๋ จ ์์
์ ์งํํ๋ค.
SQLAlchemy๋ Python์์ ์ฌ์ฉ๊ฐ๋ฅํ ORM(Object-Relational Mapping) ์ด๋ฉฐ, ๊ฐ์ฒด์ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฐ์ดํฐ๋ฅผ ์๋์ผ๋ก ๋งคํ(์ฐ๊ฒฐ)ํด์ฃผ๋ ๊ฒ์ ๋งํ๋ค.
์ฌ๊ธฐ์๋ Flask์์ ํ์ฅํํ๋ก SQLALchemy์ ์ง์ํ๋ Flask-SQLALchemy ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ค.
โ db_init.py ( ์์น: linkservice/server/db_init.py)
---------------------------------------------------------------------------------------------------------
db_init.py๋ db = SQLAlchemy() ์ ์ธ์ ํด์ฃผ๋ ๊ณตํต ๋ชจ๋๋ก ํ์ฉ ํ๋ค.
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
โ links_model.py ( ์์น: linkservice/server/models/links_model.py)
---------------------------------------------------------------------------------------------------
์ด์ ๋ถํฐ links ํ
์ด๋ธ์ ๋ํ DB๋ชจ๋ธ์ ์ ์ํ๊ณ , ๊ธฐ๋ณธ์ ์ธ id ๊ฐ์ผ๋ก ์ญ์ /์กฐํ/์
๋ฐ์ดํธ ๋ฑ ํ์ํ ๊ธฐ๋ณธ METHOD์ ์ ์ํ๋ค.
from db_init import db
from sqlalchemy import func
class LinkModel(db.Model):
# DB ์คํค๋ง๊ฐ ๊ธฐ๋ณธ(public)์ด ์๋๋ฉด ๋ณ๋๋ก ์ ์ธ์ ํด์ฃผ๋ฉด ๋๋ค.
__table_args__ = {'schema': 'aip'}
# ๋ฌผ๋ฆฌ ํ
์ด๋ธ๋ช
__tablename__ = "links"
# ์ปฌ๋ผ ๋งตํ
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100))
tag = db.Column(db.String(50))
sort = db.Column(db.Integer)
imageurl = db.Column(db.Text)
linkurl = db.Column(db.Text)
create_date = db.Column(db.Date)
update_date = db.Column(db.Date)
def __init__(self, id, name, tag, sort, imageurl, linkurl, create_date,update_date):
self.id = id
self.name = name
self.tag = tag
self.sort = sort
self.imageurl = imageurl
self.linkurl = linkurl
self.create_date = create_date
self.update_date = update_date
def save(links):
"""
์ ๋ณด ์ ์ฅ :param ์ ๋ณด ๊ฐ์ฒด
"""
db.session.merge(links)
db.session.commit()
db.session.close()
# Link์ ๋ณด ์ ์ฅ์ sort ์์์ max๊ฐ์ ๊ตฌํ๋ค. ๋ง์ฝ null์ด๋ฉด 0 ์ผ๋ก ๋ณ๊ฒฝ
# ํ๋ฉด์ ์ถ๋ ฅ๋๋ ์์๋ฅผ ๋ณ๊ฒฝํ๊ธฐ sortํญ๋ชฉ์ด ํ์ํ๋ฉฐ, ๋งํฌ์ ๋ณด ๋ฑ๋ก์ max๊ฐ์ ์ ์ฅํ๊ธฐ์ํด์ ํ์
@classmethod
def max_sort(self):
result = db.session.query(func.coalesce(func.max(self.sort), 0)).scalar()
return result+1
# ๊ธฐ๋ณธ์ ์ธ ์กฐํ/์ญ์ /์
๋ฐ์ดํธ ์ฝ๋๋ฅผ ๊ตฌ์ฑํ๋ค. ( param : id )
@classmethod
# id๋ก ์กฐํ
def find_by_id(self, id):
links= db.session.query(self).filter_by(id=id).first()
return links
@classmethod
# id๋ก ์ญ์
def delete_by_id(self, id):
try:
db.session.query(self).filter_by(id=id).delete(synchronize_session=False)
except:
db.session.rollback()
finally:
db.session.commit()
db.session.close()
@classmethod
# id๋ก values๊ฐ์ ์
๋ฐ์ดํธ
def update_by_id(self, id, values):
db.session.query(self).filter_by(id=id).update(values)
db.session.commit()
db.session.close()
def __str__(self):
return "[" + str(self.__class__) + "]: " + str(self.__dict__)
Links ํ
์ด๋ธ์ DB๋ชจ๋ธ๊ณผ ๊ธฐ๋ณธ ์ ๋ณด ์กฐํ/์ญ์ /์
๋ฐ์ดํธ ๊ด๋ จ ๋ฉ์๋๋ ์ ์์ด ๋๋ฌ์ผ๋,
์ด์ API ํํ๋ก ์ ๊ณตํ๊ณ ์ Resource๋ฅผ ์ ์ํ๋ค.
โ links.py ( ์์น: linkservice/server/src/links.py)
---------------------------------------------------------------------------------------------------
links.py์์ API ํธ์ถ ์ ์คํ๋๋ class์ ์ ์ํด๋ณด์.
- class LinkRegister(Resource) : ๋งํฌ์ ๋ณด๋ฅผ DB์ ๋ฑ๋ก(Insert) ํ๋ค.
- class LinksAll(Resource) : ์ ์ฒด ๋งํฌ ์ ๋ณด๋ฅผ ์กฐํํ๋ค.
- class LinkSelect(Resource) : ์ ํํ ๋งํฌ์ ๋ณด๋ฅผ ์กฐํํ๋ค..
- class LinkRemove(Resource) : ์ ํํ ๋งํฌ์ ๋ณด๋ฅผ ์ญ์ ํ๋ค..
- class LinkUpdate(Resource) : ์ ํํ ๋งํฌ์ ๋ณด๋ฅผ ์์ ํ๋ค..
from db_init import db
from flask_restful import Resource, reqparse
from flask import jsonify, request
from flask_marshmallow import Marshmallow
from models.links_model import LinkModel
from datetime import date as date_function
ma = Marshmallow() #๊ฐ์ฒด๋ฅผ Python ๋ฐ์ดํฐ ์ ํ์ผ๋ก ์ง๋ ฌํ
class LinkSchema(ma.SQLAlchemyAutoSchema):
class Meta:
model = LinkModel
"""
POST /api/link/create - ๋ฑ๋ก resource
"""
class LinkRegister(Resource):
# ์
๋ ฅ ํ๋ผ๋ฏธํฐ ์ค์
# DBํญ๋ชฉ์ ๋ง๊ฒ ํ๋ผ๋ฉํ๋ก ๋ฐ์ ์ ์ฅํ๋ค.
parser = reqparse.RequestParser()
parser.add_argument('name',type=str,required=True,help="ํ์ํญ๋ชฉ์
๋๋ค.")
parser.add_argument('tag',type=str)
parser.add_argument('sort',type=str)
parser.add_argument('imageurl',type=str )
parser.add_argument('linkurl',type=str )
def post(self):
# Request Parameter๋ฅผ dictionary ํํ๋ก ์ ์ฅ
data = LinkRegister.parser.parse_args()
name = data['name']
tag = data['tag']
sort = LinkModel.max_sort() #Sort์์๋ฅผ ์ํ ๊ฐ์ผ๋ก ์
๋ ฅ์ max๊ฐ์ ์
๋ ฅํ๋ค.
imageurl = data['imageurl']
linkurl = data['linkurl']
create_date = date_function.today() #create_date๋ datetime์ผ๋ก ์ ์ฅ
update_date = date_function.today()
LinkModel.save(LinkModel(None, name, tag, sort, imageurl, linkurl, create_date, update_date))
return {'message':f'๋งํฌ ์ ๋ณด๊ฐ ๋ฑ๋ก ๋์์ต๋๋ค'},201
"""
GET /api/links - ์ ์ฒด ๋งํฌ์ ๋ณด ์กฐํ
"""
class LinksAll(Resource):
def get(self):
# ์
๋ ฅ ํ๋ผ๋ฏธํฐ ์ค์ - ๋ชฉ๋ก์ ์ฒด ์ถ๋ ฅ์ผ๋ก ํ๋ผ๋ฏธํฐ๊ฐ ์์.
link = LinkModel.query.order_by(LinkModel.sort).all()
link_schema = LinkSchema(many=True)
output = link_schema.dump(link)
return jsonify({'links' : output})
"""
GET /api/link/select/<int:id> - ๋งํฌ ์ ๋ณด ์กฐํ
"""
class LinkSelect(Resource):
def get(self,id):
# ์ ๋ณด ์กฐํ
link = LinkModel.find_by_id(id)
link_schema = LinkSchema()
output = link_schema.dump(link)
return jsonify({'links' : output})
"""
DELETE /api/link/delete/<int:id> - ๋งํฌ์ ๋ณด์ญ์
"""
class LinkRemove(Resource):
def delete(self, id):
# ์ ๋ณด ์ญ์ ( links_model์ delete_by_id ๋ฉ์๋ ํธ์ถ )
LinkModel.delete_by_id(id)
return {'message':'์ ์์ ์ผ๋ก ์ญ์ ๋์์ต๋๋ค.'},201
"""
PUT /api/link/update/<int:id> - ๋งํฌ ์ ๋ณด ์์
"""
class LinkUpdate(Resource):
def put(self,id):
#Request๋ฅผ json์ผ๋ก ๋ฐ๋๋ค.
values = request.get_json()
# ์ ๋ณด ์์ ( links_model์ update_by_id ๋ฉ์๋ ํธ์ถ )
LinkModel.update_by_id(id, values)
return {'message':'์ ๋ณด๊ฐ ์์ ๋์์ต๋๋ค.'},201
์ฐธ๊ณ ์๋ฃ :
Sqlalchemy
Flask + marshmallow for beautiful APIs
๋ค์ ํธ์๋ server.py์ flask_restful์์ ์ ๊ณต๋๋ API Resource์ ์ถ๊ฐํด ๋ณด์.