aiohttp를 사용하여 REST API를 만드는 방법
AsyncIO은 쓰기를 위한 python 라이브러리입니다.
이는 특히 소켓 및 기타 리소스를 통한 I/O 바운드 작업에 대한 동시성을 제공합니다. 동시성은 사용자가 I/O 바운드 결과를 기다리지 않도록 합니다.
이 기사에서는 aiohttp를 사용하여 애플리케이션에 대한 나머지 API를 작성합니다. 메모 테이블이 있는 간단한 응용 프로그램입니다.
aiohttp 설정
Python 3에서 가상 환경을 활성화하고 aiohttp를 설치합니다.
pip install aiohttp
또는 github 저장소를 복제하고 요구 사항을 설치하십시오.
pip install -r requirements.txt
모델 만들기
models.py
에서 sqlite를 데이터베이스로 사용하도록 애플리케이션을 구성합니다.# DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
DB_URI = 'sqlite:///stuff.db'
Session = sessionmaker(autocommit=False,
autoflush=False,
bind=create_engine(DB_URI))
session = scoped_session(Session)
Base = declarative_base()
그런 다음
models.py
에서 메모 개체에 대한 메모 클래스를 만듭니다.class Note(Base):
__tablename__ = 'notes'
id = Column(Integer, primary_key=True)
title = Column(String(50))
description = Column(String(50))
created_at = Column(String(50))
created_by = Column(String(50))
priority = Column(Integer)
def __init__(self, title, description, created_at ,created_by, priority):
self.title = title
self.description = description
self.created_at = created_at
self.created_by = created_by
self.priority = priority
@classmethod
def from_json(cls, data):
return cls(**data)
def to_json(self):
to_serialize = ['id', 'title', 'description', 'created_at', 'created_by', 'priority']
d = {}
for attr_name in to_serialize:
d[attr_name] = getattr(self, attr_name)
return d
자원
aiohttp_rest.py
파일에 API 끝점을 정의합니다.DEFAULT_METHODS = ('GET', 'POST', 'PUT', 'DELETE')
class RestEndpoint:
def __init__(self):
self.methods = {}
for method_name in DEFAULT_METHODS:
method = getattr(self, method_name.lower(), None)
if method:
self.register_method(method_name, method)
def register_method(self, method_name, method):
self.methods[method_name.upper()] = method
async def dispatch(self, request: Request):
method = self.methods.get(request.method.upper())
if not method:
raise HTTPMethodNotAllowed('', DEFAULT_METHODS)
wanted_args = list(inspect.signature(method).parameters.keys())
available_args = request.match_info.copy()
available_args.update({'request': request})
unsatisfied_args = set(wanted_args) - set(available_args.keys())
if unsatisfied_args:
# Expected match info that doesn't exist
raise HttpBadRequest('')
return await method(**{arg_name: available_args[arg_name] for arg_name in wanted_args})
class CollectionEndpoint(RestEndpoint):
def __init__(self, resource):
super().__init__()
self.resource = resource
async def get(self) -> Response:
data = []
notes = session.query(Note).all()
for instance in self.resource.collection.values():
data.append(self.resource.render(instance))
data = self.resource.encode(data)
return Response ( status=200, body=self.resource.encode({
'notes': [
{'id': note.id, 'title': note.title, 'description': note.description,
'created_at': note.created_at, 'created_by': note.created_by, 'priority': note.priority}
for note in session.query(Note)
]
}), content_type='application/json')
async def post(self, request):
data = await request.json()
note=Note(title=data['title'], description=data['description'], created_at=data['created_at'], created_by=data['created_by'], priority=data['priority'])
session.add(note)
session.commit()
return Response(status=201, body=self.resource.encode({
'notes': [
{'id': note.id, 'title': note.title, 'description': note.description,
'created_at': note.created_at, 'created_by': note.created_by, 'priority': note.priority}
for note in session.query(Note)
]
}), content_type='application/json')
class InstanceEndpoint(RestEndpoint):
def __init__(self, resource):
super().__init__()
self.resource = resource
async def get(self, instance_id):
instance = session.query(Note).filter(Note.id == instance_id).first()
if not instance:
return Response(status=404, body=json.dumps({'not found': 404}), content_type='application/json')
data = self.resource.render_and_encode(instance)
return Response(status=200, body=data, content_type='application/json')
async def put(self, request, instance_id):
data = await request.json()
note = session.query(Note).filter(Note.id == instance_id).first()
note.title = data['title']
note.description = data['description']
note.created_at = data['created_at']
note.created_by = data['created_by']
note.priority = data['priority']
session.add(note)
session.commit()
return Response(status=201, body=self.resource.render_and_encode(note),
content_type='application/json')
async def delete(self, instance_id):
note = session.query(Note).filter(Note.id == instance_id).first()
if not note:
abort(404, message="Note {} doesn't exist".format(id))
session.delete(note)
session.commit()
return Response(status=204)
class RestResource:
def __init__(self, notes, factory, collection, properties, id_field):
self.notes = notes
self.factory = factory
self.collection = collection
self.properties = properties
self.id_field = id_field
self.collection_endpoint = CollectionEndpoint(self)
self.instance_endpoint = InstanceEndpoint(self)
def register(self, router: UrlDispatcher):
router.add_route('*', '/{notes}'.format(notes=self.notes), self.collection_endpoint.dispatch)
router.add_route('*', '/{notes}/{{instance_id}}'.format(notes=self.notes), self.instance_endpoint.dispatch)
def render(self, instance):
return OrderedDict((notes, getattr(instance, notes)) for notes in self.properties)
@staticmethod
def encode(data):
return json.dumps(data, indent=4).encode('utf-8')
def render_and_encode(self, instance):
return self.encode(self.render(instance))
모든 메서드(GET, POST, PUT 및 DELETE)와 함께 async 키워드를 사용하여 이러한 작업이 비동기적으로 수행되고 응답이 수집 끝점과 인스턴스 끝점 모두에서 반환되도록 합니다. 엔드포인트를 설정한 후
aio-app.py
파일에서 리소스를 선언합니다.from aiohttp.web import Application, run_app
from aiohttp_rest import RestResource
from models import Note
from sqlalchemy import engine_from_config
notes = {}
app = Application()
person_resource = RestResource('notes', Note, notes, ('title', 'description', 'created_at', 'created_by', 'priority'), 'title')
person_resource.register(app.router)
if __name__ == '__main__':
run_app(app)
애플리케이션 실행
먼저 다음을 수행하여 데이터베이스를 생성합니다.
python models.py
터미널에서 다음을 실행하여 앱을 실행합니다.
python aio-app.py
파이썬 셸을 열고 일부 요청을 실행합니다.
requests.post('http://localhost:8080/notes',
data=json.dumps({ "title": "note two",
"created_at": "2017-08-23 00:00", "created_by": "apcelent", "description": "sample notes", "priority": 4
}))
requests.put('http://localhost:8080/notes/1',
data=json.dumps({ "title": "note edit",
"created_at": "2017-08-23 00:00", "created_by": "apcelent", "description": "sample notes edit", "priority": 4
}))
requests.delete('http://localhost:8080/notes/1')
이들은 aiohttp REST API를 사용하여 데이터베이스에 일부 메모를 생성합니다. 이 메모는 http://127.0.0.1:8080/notes에서 볼 수 있습니다.
소스 코드는 here에서 찾을 수 있습니다.
이 기사는 원래 Apcelent Tech Blog에 게재되었습니다.
Reference
이 문제에 관하여(aiohttp를 사용하여 REST API를 만드는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/apcelent/how-to-create-rest-api-using-aiohttp-54p1텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)