2017-03-27 22:47:35 +01:00
|
|
|
from sanic import Sanic
|
2017-05-11 18:15:04 +01:00
|
|
|
from sanic.exceptions import NotFound, URLBuildError
|
2017-03-27 22:47:35 +01:00
|
|
|
from sanic.response import json
|
|
|
|
from sanic.views import HTTPMethodView
|
|
|
|
|
|
|
|
from asyncorm import configure_orm
|
|
|
|
from asyncorm.exceptions import QuerysetError
|
|
|
|
|
|
|
|
from library.models import Book
|
|
|
|
from library.serializer import BookSerializer
|
|
|
|
|
|
|
|
app = Sanic(name=__name__)
|
|
|
|
|
|
|
|
|
|
|
|
@app.listener('before_server_start')
|
|
|
|
def orm_configure(sanic, loop):
|
|
|
|
db_config = {'database': 'sanic_example',
|
|
|
|
'host': 'localhost',
|
2017-05-29 00:01:56 +01:00
|
|
|
'user': 'ormdbuser',
|
|
|
|
'password': 'ormDbPass',
|
2017-03-27 22:47:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
# configure_orm needs a dictionary with:
|
|
|
|
# * the database configuration
|
|
|
|
# * the application/s where the models are defined
|
|
|
|
orm_app = configure_orm({'loop': loop, # always use the sanic loop!
|
|
|
|
'db_config': db_config,
|
|
|
|
'modules': ['library', ], # list of apps
|
|
|
|
})
|
|
|
|
|
|
|
|
# orm_app is the object that orchestrates the whole ORM
|
|
|
|
# sync_db should be run only once, better do that as external command
|
|
|
|
# it creates the tables in the database!!!!
|
|
|
|
# orm_app.sync_db()
|
|
|
|
|
|
|
|
|
|
|
|
# for all the 404 lets handle the exceptions
|
|
|
|
@app.exception(NotFound)
|
|
|
|
def ignore_404s(request, exception):
|
|
|
|
return json({'method': request.method,
|
|
|
|
'status': exception.status_code,
|
|
|
|
'error': exception.args[0],
|
|
|
|
'results': None,
|
|
|
|
})
|
|
|
|
|
|
|
|
|
2017-05-29 00:01:56 +01:00
|
|
|
@app.exception(URLBuildError)
|
|
|
|
def ignore_urlbuilderrors(request, exception):
|
|
|
|
return json({'method': request.method,
|
|
|
|
'status': exception.status_code,
|
|
|
|
'error': exception.args[0],
|
|
|
|
'results': None,
|
|
|
|
})
|
|
|
|
|
|
|
|
|
2017-03-27 22:47:35 +01:00
|
|
|
# now the propper sanic workflow
|
|
|
|
class BooksView(HTTPMethodView):
|
|
|
|
|
|
|
|
async def get(self, request):
|
2017-05-11 18:15:04 +01:00
|
|
|
filtered_by = request.raw_args
|
2017-03-27 22:47:35 +01:00
|
|
|
|
|
|
|
if filtered_by:
|
2017-05-11 18:15:04 +01:00
|
|
|
try:
|
|
|
|
q_books = Book.objects.filter(**filtered_by)
|
|
|
|
except AttributeError as e:
|
|
|
|
raise URLBuildError(e.args[0])
|
2017-03-27 22:47:35 +01:00
|
|
|
else:
|
2017-05-11 18:15:04 +01:00
|
|
|
q_books = Book.objects.all()
|
2017-03-27 22:47:35 +01:00
|
|
|
|
2017-05-11 18:15:04 +01:00
|
|
|
books = []
|
|
|
|
async for book in q_books:
|
|
|
|
books.append(BookSerializer.serialize(book))
|
2017-03-27 22:47:35 +01:00
|
|
|
|
|
|
|
return json({'method': request.method,
|
|
|
|
'status': 200,
|
|
|
|
'results': books or None,
|
|
|
|
'count': len(books),
|
|
|
|
})
|
|
|
|
|
|
|
|
async def post(self, request):
|
|
|
|
# populate the book with the data in the request
|
|
|
|
book = Book(**request.json)
|
|
|
|
|
|
|
|
# and await on save
|
|
|
|
await book.save()
|
|
|
|
|
|
|
|
return json({'method': request.method,
|
|
|
|
'status': 201,
|
|
|
|
'results': BookSerializer.serialize(book),
|
|
|
|
})
|
|
|
|
|
2017-05-29 00:01:56 +01:00
|
|
|
|
2017-03-27 22:47:35 +01:00
|
|
|
class BookView(HTTPMethodView):
|
|
|
|
async def get_object(self, request, book_id):
|
|
|
|
try:
|
|
|
|
# await on database consults
|
|
|
|
book = await Book.objects.get(**{'id': book_id})
|
|
|
|
except QuerysetError as e:
|
|
|
|
raise NotFound(e.args[0])
|
|
|
|
return book
|
|
|
|
|
|
|
|
async def get(self, request, book_id):
|
|
|
|
# await on database consults
|
|
|
|
book = await self.get_object(request, book_id)
|
|
|
|
|
|
|
|
return json({'method': request.method,
|
|
|
|
'status': 200,
|
|
|
|
'results': BookSerializer.serialize(book),
|
|
|
|
})
|
|
|
|
|
|
|
|
async def put(self, request, book_id):
|
|
|
|
# await on database consults
|
|
|
|
book = await self.get_object(request, book_id)
|
|
|
|
# await on save
|
|
|
|
await book.save(**request.json)
|
|
|
|
|
|
|
|
return json({'method': request.method,
|
|
|
|
'status': 200,
|
|
|
|
'results': BookSerializer.serialize(book),
|
|
|
|
})
|
|
|
|
|
|
|
|
async def patch(self, request, book_id):
|
|
|
|
# await on database consults
|
|
|
|
book = await self.get_object(request, book_id)
|
|
|
|
# await on save
|
|
|
|
await book.save(**request.json)
|
|
|
|
|
|
|
|
return json({'method': request.method,
|
|
|
|
'status': 200,
|
|
|
|
'results': BookSerializer.serialize(book),
|
|
|
|
})
|
|
|
|
|
|
|
|
async def delete(self, request, book_id):
|
|
|
|
# await on database consults
|
|
|
|
book = await self.get_object(request, book_id)
|
|
|
|
# await on its deletion
|
|
|
|
await book.delete()
|
|
|
|
|
|
|
|
return json({'method': request.method,
|
|
|
|
'status': 200,
|
|
|
|
'results': None
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
app.add_route(BooksView.as_view(), '/books/')
|
|
|
|
app.add_route(BookView.as_view(), '/books/<book_id:int>/')
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2017-05-29 00:01:56 +01:00
|
|
|
app.run(port=9000, debug=True)
|