Generic
We assume you could run the project with Introduction
Now let's write custom APIs for Create
, Retrieve
, Update
and Delete
a Book
:
Structure & Requirements#
Create Model#
Create a model named Book
in app/models.py
:
from panther.db import Model
class Book(Model):
name: str
author: str
pages_count: int
Create API Class#
Create the BookAPI()
in app/apis.py
:
from panther.app import GenericAPI
class BookAPI(GenericAPI):
...
We are going to complete it later ...
Update URLs#
Add the BookAPI
in app/urls.py
:
from app.apis import BookAPI
urls = {
'book/': BookAPI,
}
We assume that the urls
in core/urls.py
pointing to app/urls.py
, like below:
from app.urls import urls as app_urls
urls = {
'/': app_urls,
}
Add Database#
Add DATABASE
in configs
, we are going to add pantherdb
PantherDB is a Simple, File-Base and Document Oriented database
...
DATABASE = {
'engine': {
'class': 'panther.db.connections.PantherDBConnection',
}
}
...
APIs#
API - Create a Book#
Now we are going to create a book on POST
request, we need to:
-
Inherit from
CreateAPI
:from panther.generics import CreateAPI class BookAPI(CreateAPI): ...
-
Create a ModelSerializer in
app/serializers.py
, forvalidation
of therequest.data
:from panther.serializer import ModelSerializer from app.models import Book class BookSerializer(ModelSerializer): class Config: model = Book fields = ['name', 'author', 'pages_count']
-
Set the created serializer in
BookAPI
asinput_model
:from panther.app import CreateAPI from app.serializers import BookSerializer class BookAPI(CreateAPI): input_model = BookSerializer
It is going to create a Book
with incoming request.data
and return that instance to user with status code of 201
API - List of Books#
Let's return list of books of GET
method, we need to:
-
Inherit from
ListAPI
from panther.generics import CreateAPI, ListAPI from app.serializers import BookSerializer class BookAPI(CreateAPI, ListAPI): input_model = BookSerializer ...
-
define
cursor
method, so theListAPI
knows to return which booksfrom panther.generics import CreateAPI, ListAPI from panther.request import Request from app.models import Book from app.serializers import BookSerializer class BookAPI(CreateAPI, ListAPI): input_model = BookSerializer async def cursor(self, request: Request, **kwargs): return await Book.find()
Pagination, Search, Filter, Sort#
Pagination#
Use panther.pagination.Pagination
as pagination
Usage: It will look for the limit
and skip
in the query params
and return its own response template
Example: ?limit=10&skip=20
Search#
Define the fields you want the search, query on them in search_fields
The value of search_fields
should be list
Usage: It works with search
query param --> ?search=maybe_name_of_the_book_or_author
Example: ?search=maybe_name_of_the_book_or_author
Filter#
Define the fields you want to be filterable in filter_fields
The value of filter_fields
should be list
Usage: It will look for each value of the filter_fields
in the query params
and query on them
Example: ?name=name_of_the_book&author=author_of_the_book
Sort#
Define the fields you want to be sortable in sort_fields
The value of sort_fields
should be list
Usage: It will look for each value of the sort_fields
in the query params
and sort with them
Example: ?sort=pages_count,-name
Notice:
- fields should be separated with a column ,
- use field_name
for ascending sort
- use -field_name
for descending sort
Example#
from panther.generics import CreateAPI, ListAPI
from panther.pagination import Pagination
from panther.request import Request
from app.models import Book
from app.serializers import BookSerializer, BookOutputSerializer
class BookAPI(CreateAPI, ListAPI):
input_model = BookSerializer
output_model = BookOutputSerializer
pagination = Pagination
search_fields = ['name', 'author']
filter_fields = ['name', 'author']
sort_fields = ['name', 'pages_count']
async def cursor(self, request: Request, **kwargs):
return await Book.find()
API - Retrieve a Book#
Now we are going to retrieve a book on GET
request, we need to:
-
Inherit from
RetrieveAPI
:from panther.generics import RetrieveAPI class SingleBookAPI(RetrieveAPI): ...
-
define
object
method, so theRetrieveAPI
knows to return which bookfrom panther.generics import RetrieveAPI from panther.request import Request from app.models import Book class SingleBookAPI(RetrieveAPI): async def object(self, request: Request, **kwargs): return await Book.find_one_or_raise(id=kwargs['book_id'])
-
Add it in
app/urls.py
:from app.apis import BookAPI, SingleBookAPI urls = { 'book/': BookAPI, 'book/<book_id>/': SingleBookAPI, }
You should write the Path Variable in
<
and>
API - Update a Book#
-
Inherit from
UpdateAPI
from panther.generics import RetrieveAPI, UpdateAPI from panther.request import Request from app.models import Book class SingleBookAPI(RetrieveAPI, UpdateAPI): ... async def object(self, request: Request, **kwargs): return await Book.find_one_or_raise(id=kwargs['book_id'])
-
Add
input_model
so theUpdateAPI
knows how to validate therequest.data
We use the same serializer as CreateAPI serializer we defined above
from panther.generics import RetrieveAPI, UpdateAPI from panther.request import Request from app.models import Book from app.serializers import BookSerializer class SingleBookAPI(RetrieveAPI, UpdateAPI): input_model = BookSerializer async def object(self, request: Request, **kwargs): return await Book.find_one_or_raise(id=kwargs['book_id'])
API - Delete a Book#
-
Inherit from
DeleteAPI
from panther.generics import RetrieveAPI, UpdateAPI, DeleteAPI from panther.request import Request from app.models import Book from app.serializers import BookSerializer class SingleBookAPI(RetrieveAPI, UpdateAPI, DeleteAPI): input_model = BookSerializer async def object(self, request: Request, **kwargs): return await Book.find_one_or_raise(id=kwargs['book_id'])
-
It requires
object
method which we defined before, so it's done.