Flask RESTful API - PATCH /stores (현재 위치 기준 지정한 반경내 모든 매장 정보 등록)
2019. 7. 3. 11:27ㆍPython/Flask
반응형
PATCH /stores
사용자가 지정한 위도,경도,반경 기준에 해당 하는 매장 정보를 저장 한다.
저장 시 기존에 저장한 매장 정보를 조회 하여서 일치하는 정보가 있는 경우 업데이트 하고 일치하는 정보가 없는 경우 저장 처리 한다.
Kakao API를 호출 하면 한번에 15건씩 조회 결과를 받을 수 있다 하지만 반경을 크게 주면 15개 이상의 매장이 검색 될 것이다.
게시판 페이징 처리 처럼 페이징 처리를 통하여 모든 데이터를 저정해야 한다.
아래 그림을 보면 대략 10km 기준으로 검색 해보면 40개 이상 매장이 검색 될 것이다.
Resource URL
Kakao api 연동: http://localhost:5000/stores/create
Request
{
"place_name":"스타벅스",
"x":37.6125901,
"y":126.7284632,
"radius":"10000"
}
Response
{
"message": "총 47 건의 매장 정보가 등록 되었습니다."
}
소스코드 작성
앞에 코드에 메소드를 추가해 나가면 된다.
소스코드 작성은 다음과 같이 작성한다.
- 기존 매장 정보 검색 메소드 추가
- 매장 정보 등록을 위한 메소드 추가
- app.py Resource 정보 등록
store.py - Model
Kakao API 조회 후 조회된 매장 정보가 기존에 등록된 경우 업데이트 처리를 위한 조회 메소드
@classmethod def find_store_by_store_name_with_adress(self, place_name, road_address): """ 매장 정보 조회 param place_name: 장소명 param road_address: 도로명주소 :return: store: 조회된 매장 정보 객체 """ return db.session.query(self).filter_by(store_name=place_name).filter_by(road_address=road_address).first()
store.py - Resource
""" PATCH /stores - 현재 위치 기준 지정한 반경내 모든 매장 정보 등록 """ class StoresRegister(Resource): # 입력 파라미터 설정 parser = reqparse.RequestParser() parser.add_argument('place_name', type=str, required=False ) parser.add_argument('x', type=float, required=False ) parser.add_argument('y', type=float, required=False ) parser.add_argument('radius', type=float, required=False ) def patch(self): # Request Parameter를 dictionary 형태로 저장 37.5950084,126.7656567 data = StoresRegister.parser.parse_args() # 장소명 place_name = data['place_name'] # 위도 y = data['y'] # 경도 x = data['x'] # 뱐경 radius = data['radius'] # 저장 처리를 위한 매장 리스트 store_list = [] # 페이지당건수 per_page_count = 15 # 총 페이지 total_page = 1 # 페이지 page = 1 """ Kakao API 검색 결과는 기본적으로 한번에 15건을 조회 결과로 리턴 해 준다. 만약 건수가 15건이 넘어가는 경우 페이징 처리가 필요하다. 이를 위해서 클로저 함수를 이용한다. """ def make_stores(response): for store in response['documents']: """ 단일건으로 등록한 매장 정보의 경우 주소 정보로 위치 정보를 저장 하게 된다. 실제로는 위치정보가 장소명으로 검색한 경우와 불일치 하므로 기존 매장 정보 검색 후 일치하는 정보가 있는 경우 장소명으로 검색한 정보로 업데이트 처리 하기 위해 기존 매장 정보 검색 후 매장 정보를 설정한다. """ store_info = StoreModel.find_store_by_store_name_with_adress(store['place_name'],store['road_address_name']) if store_info: # Geometry 정보 설정 point = 'POINT({} {})'.format(store_info.lat, store_info.lon) # point 정보를 바로 저장 할 시 우리나라 좌표계와 맞지 않으므로 좌표계를 변환 처리 한다. geo = StoreModel.convert_geom(point) # 매장 리스트에 append 처리 store_list.append(StoreModel(store_info.store_id,store['place_name'],store['address_name'],store['road_address_name'],store['phone'],store['place_url'],None,store['x'],store['y'],geo)) else: # 검색 결과에서 카테고리 그룹코드가 CE7 인경우 카페 이므로 그룹코드가 CE7인 경우만 리슽에 저장 if store['category_group_code'] == 'CE7': # Geometry 정보 설정 point = 'POINT({} {})'.format(store['x'], store['y']) # point 정보를 바로 저장 할 시 우리나라 좌표계와 맞지 않으므로 좌표계를 변환 처리 한다. geo = StoreModel.convert_geom(point) # 매장 리스트에 append 처리 store_list.append(StoreModel(None, store['place_name'],store['address_name'],store['road_address_name'],store['phone'],store['place_url'],None,store['x'],store['y'],geo)) # Kakao API를 검색을 통해 위치 정보를 입수한다. response = find_place(y ,x, radius, place_name, 1) # 총 조회 데이터 건수 total_count = response['meta']['total_count'] # 총 페이지 계산 if total_count % per_page_count == 0: total_page = int(total_count / per_page_count) else: total_page = int((total_count / per_page_count) + 1) # 조회결과를 저장 처리를 위한 리스트 변수 저장 클로저 함수 호출 make_stores(response) # 조회 결과 가 없는 경우 if total_count == 0: return {'message': '매장 정보가 존재 하지 않습니다.'}, 404 else: for page in range(total_page): """ page 기본값은 0 이지만 위에서 첫번째 페이지 건으로 조회 하였기 때문에 그 다음 page 인 2page 조회 를 위해서 page + 2로 해준다. """ page = page + 2 # Kakao API를 검색을 통해 위치 정보를 입수한다. response = find_place(y ,x, radius, place_name, page) # 조회결과를 저장 처리를 위한 리스트 변수 저장 클로저 함수 호출 make_stores(response) # 매장 정보 저장/업데이트 처리 total_save_count = 0 if len(store_list) > 0: total_save_count = len(store_list) - 1 for store in store_list: StoreModel.save(store) return {'message':'총 {} 건의 매장 정보가 등록 되었습니다.'.format(total_save_count)},201
app.py
import os import psycopg2 from flask import Flask from flask_restful import Api from flask_sqlalchemy import SQLAlchemy from config import app_config from resources.store import StoreRegister,StoresRegister # set_env.bat 에서 설정한 application 이름 설정 app = Flask(os.getenv('FLASK_APP')) # set_env.bat 에서 설정한 FLASK_ENV는 development env_name = os.getenv('FLASK_ENV') """ app_config 는 config.py 에서 정의 app_config 이면 위에서 development를 설정하였기 때문에 config.py 의 Development 클래스의 정보가 설정 되게 된다. """ app.config.from_object(app_config[env_name]) # 데이터 변경사항에 대해 커밋 전후로 알림 여부 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # Query Debug 여부 app.config['SQLALCHEMY_ECHO'] = False """ API Resource 등록 --------------------------------------------------------- POST /stores/create - 매장 등록 PATCH /stores - 벌크 매장 등록 GET /stores - 매장목록 조회 GET /stores/<int:store_id> - 매장정보조회 DELETE /stores/<int:store_id> - 매장정보삭제 """ api = Api(app) api.add_resource(StoreRegister, '/stores/create') api.add_resource(StoresRegister, '/stores') if __name__ == "__main__": from db_init import db db.init_app(app) app.run(debug=True,port=5000)
테스트
아래 그림과 같이 장소명 현재 위치 정보를 입력 파라미터로 설정 한 후 테스트 한다.
반응형
'Python > Flask' 카테고리의 다른 글
Flask RESTful API - GET /stores/{store_id} (매장상세정보조회 및 평점업데이트) (0) | 2019.07.03 |
---|---|
Flask RESTful API - GET /stores/search (매장검색) (0) | 2019.07.03 |
Flask RESTful API - POST /stores/create (매장등록) (0) | 2019.07.02 |
Flask RESTful API - 서버 환경 설정 (0) | 2019.07.01 |
Flask RESTful API - 매장관리 API URL 및 테이블 설계 (0) | 2019.07.01 |