First CRUD
We assume you have successfully set up your project following the Introduction guide.
In this guide, we will create a CRUD
(Create
, Retrieve
, Update
, and Delete
) API for managing Book
entities.
Project Structure
The final structure of your project will be as follows:
.
├── app
│ ├── apis.py
│ ├── models.py
│ ├── serializers.py
│ └── urls.py
└── core
├── configs.py
└── urls.py
Configuring the Database
How does the database work in Panther?
Refer to Database to learn about supported databases and their functionality.
Configure the DATABASE
settings in core/configs.py
. In this guide, we will use PantherDB
.
PantherDB is a simple, file-based, document-oriented database.
core/configs.py DATABASE = {
'engine' : {
'class' : 'panther.db.connections.PantherDBConnection' ,
}
}
Defining the Model
How do models work in Panther?
Refer to Models to learn more about defining models and how they function.
Create a model named Book
in app/models.py
:
app/models.py from panther.db import Model
class Book ( Model ):
name : str
author : str
pages_count : int
Defining URLs
How do URLs work in Panther?
Refer to URLs to learn more about URL definitions.
The base urls
configuration should include all application URLs.
core/urls.py from app.urls import urls as app_urls
urls = {
'/' : app_urls ,
}
In app/urls.py
, define the Book
API URLs:
Defining the Serializer
How do serializers work in Panther?
Refer to Serializer to learn more about available serializers.
Serializers transform data between the application and API requests.
APIs
How do APIs work in Panther?
Refer to API to learn more about API types and their usage.
Create
Function-Base API Class-Base API Generic API (Beta)
app/apis.py 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 from panther import status
from panther.app import API
from panther.request import Request
from panther.response import Response
from app.serializers import BookSerializer
from app.models import Book
@API ( input_model = BookSerializer , methods = [ 'POST' ])
async def book_api ( request : Request ):
body : BookSerializer = request . validated_data
book : Book = await Book . insert_one (
name = body . name ,
author = body . author ,
pages_count = body . pages_count ,
)
return Response ( data = book , status_code = status . HTTP_201_CREATED )
app/apis.py 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 from panther import status
from panther.app import GenericAPI
from panther.request import Request
from panther.response import Response
from app.serializers import BookSerializer
from app.models import Book
class BookAPI ( GenericAPI ):
input_model = BookSerializer
async def post ( self , request : Request ):
body : BookSerializer = request . validated_data
book = await Book . insert_one (
name = body . name ,
author = body . author ,
pages_count = body . pages_count ,
)
return Response ( data = book , status_code = status . HTTP_201_CREATED )
app/apis.py from panther.app import CreateAPI
from app.serializers import BookSerializer
class BookAPI ( CreateAPI ):
input_model = BookSerializer
List
Function-Base API Class-Base API Generic API (Beta)
app/apis.py 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 from panther import status
from panther.app import API
from panther.request import Request
from panther.response import Response
from app.serializers import BookSerializer
from app.models import Book
@API ( input_model = BookSerializer , methods = [ 'POST' , 'GET' ])
async def book_api ( request : Request ):
...
if request . method == 'GET' :
books = await Book . find ()
return Response ( data = books , status_code = status . HTTP_200_OK )
app/apis.py 1
2
3
4
5
6
7
8
9
10
11
12
13
14 from panther import status
from panther.app import GenericAPI
from panther.response import Response
from app.serializers import BookSerializer
from app.models import Book
class BookAPI ( GenericAPI ):
input_model = BookSerializer
async def get ( self ):
books = await Book . find ()
return Response ( data = books , status_code = status . HTTP_200_OK )
app/apis.py 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 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
class BookAPI ( CreateAPI , ListAPI ):
input_model = BookSerializer
pagination = Pagination #(1)!
search_fields = [ 'name' , 'author' ] #(2)!
filter_fields = [ 'name' , 'author' ] #(3)!
sort_fields = [ 'name' , 'pages_count' ] #(4)!
async def cursor ( self , request : Request , ** kwargs ):
return await Book . find ()
Pagination
class will look for the limit
and skip
in the query params
and paginate your response and then return it on its own response template.
The query will be changed and looking for the value of the search
query param in these fields,
e.g. query param is the ?search=TheLittlePrince
, we will looking for the Book with name
or author
of TheLittlePrince
.
It will look for each value of the filter_fields
in the query params
and query on them,
e.g. ?name=Something&author=Ali
, it will looks for Book that its author
is Ali
and its name
is Something
.
The query will be sortalbe with the fields which is in sort_fields
.
Retrieve
Update
Function-Base API Class-Base API Generic API (Beta)
app/apis.py 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 from panther import status
from panther.app import API
from panther.request import Request
from panther.response import Response
from app.models import Book
from app.serializers import BookSerializer
@API ( input_model = BookSerializer , methods = [ 'GET' , 'PUT' ])
async def single_book_api ( request : Request , book_id : int ):
...
if request . method == 'PUT' :
is_updated = await Book . update_one ({ 'id' : book_id }, request . validated_data . model_dump ())
data = { 'is_updated' : is_updated }
return Response ( data = data , status_code = status . HTTP_200_OK )
app/apis.py 1
2
3
4
5
6
7
8
9
10
11
12
13
14 from panther import status
from panther.app import GenericAPI
from panther.response import Response
from app.models import Book
class SingleBookAPI ( GenericAPI ):
input_model = BookSerializer
async def put ( self , request : Request , book_id : int ):
is_updated = await Book . update_one ({ 'id' : book_id }, request . validated_data . model_dump ())
data = { 'is_updated' : is_updated }
return Response ( data = data , status_code = status . HTTP_200_OK )
app/apis.py 1
2
3
4
5
6
7
8
9
10
11
12 from panther.generics import RetrieveAPI
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' ])
Delete
With this, you now have a complete CRUD API implementation for the Book
entity.