Application Architecture

Resource Layer (Flask-RESTful Resources)

The Resource layer maps HTTP endpoints to Python classes. Each Resource encapsulates request parsing, authentication, and CRUD logic. Flask-RESTful handles routing and serialization.


📚 Book Resource

The Book resource manages individual books and the book list. It uses a shared parser for input validation and JWT for secure reads.

from flask_restful import Resource, reqparse
from flask_jwt import jwt_required
from models.book import BookModel

class Book(Resource):
    parser = reqparse.RequestParser()
    parser.add_argument('price', 
        type=float, required=True, help="This field cannot be left blank!")
    parser.add_argument('store_id', 
        type=int, required=True, help="Every item needs a store_id.")
    parser.add_argument('author', 
        type=str, required=True, help="Every item needs a author.")
    parser.add_argument('isbn', 
        type=str, required=True, help="Every item needs a isbn.")
    parser.add_argument('release_date', 
        type=str, required=False)
    ...    

Derived from the source code .

Parser Arguments

Argument Type Required Description
price float Yes Price of the book.
store_id int Yes Foreign key to the owning Store.
author str Yes Book author’s name.
isbn str Yes International Standard Book Number.
release_date str No Publication date (YYYY-MM-DD).

Resource Methods

Method Description
@jwt_required()get(title) Return book JSON or 404 if not found.
post(title) Create new book after validating uniqueness; return 201 or 400/500 on failure.
delete(title) Remove book by title; return success or 404.
put(title) Update price if exists, else create a new book; return book JSON.
BookList.get() Return {'books': [...]} array of all BookModel JSON.

Source: resources/book.py .


GET /book/{title}

{
    "title": "Retrieve a Book",
    "description": "Fetch a single book by title. Requires JWT authentication.",
    "method": "GET",
    "baseUrl": "http://localhost:5000",
    "endpoint": "/book/{title}",
    "headers": [
        { "key": "Authorization", "value": "JWT <token>", "required": true }
    ],
    "pathParams": [
        { "key": "title", "value": "Book title", "required": true }
    ],
    "bodyType": "none",
    "responses": {
        "200": {
            "description": "Book found",
            "body": "{\n  \"title\": \"Kalinga\",\n  \"price\": 200.0,\n  \"author\": \"sapan mohanty\",\n  \"isbn\": \"WER3455\",\n  \"release_date\": \"2020-12-12\"\n}"
        },
        "404": {
            "description": "Book not found",
            "body": "{ \"message\": \"book not found\" }"
        }
    }
}

POST /book/{title}

{
    "title": "Create a Book",
    "description": "Add a new book with given title. Validates uniqueness.",
    "method": "POST",
    "baseUrl": "http://localhost:5000",
    "endpoint": "/book/{title}",
    "headers": [
        { "key": "Authorization", "value": "JWT <token>", "required": true },
        { "key": "Content-Type", "value": "application/json", "required": true }
    ],
    "pathParams": [
        { "key": "title", "value": "Book title", "required": true }
    ],
    "bodyType": "json",
    "requestBody": "{\n  \"price\": 19.99,\n  \"store_id\": 1,\n  \"author\": \"Jane Doe\",\n  \"isbn\": \"ABC123\",\n  \"release_date\": \"2021-01-01\"\n}",
    "responses": {
        "201": {
            "description": "Book created",
            "body": "{ \"title\": \"NewBook\", \"price\": 19.99, \"author\": \"Jane Doe\", \"isbn\": \"ABC123\", \"release_date\": \"2021-01-01\" }"
        },
        "400": {
            "description": "Duplicate title",
            "body": "{ \"message\": \"An book with title 'NewBook' already exists.\" }"
        },
        "500": {
            "description": "Insertion error",
            "body": "{ \"message\": \"An error occurred inserting the book.\" }"
        }
    }
}

DELETE /book/{title}

{
    "title": "Delete a Book",
    "description": "Remove a book by title.",
    "method": "DELETE",
    "baseUrl": "http://localhost:5000",
    "endpoint": "/book/{title}",
    "headers": [],
    "pathParams": [
        { "key": "title", "value": "Book title", "required": true }
    ],
    "bodyType": "none",
    "responses": {
        "200": {
            "description": "Deletion succeeded",
            "body": "{ \"message\": \"Item deleted.\" }"
        },
        "404": {
            "description": "Item not found",
            "body": "{ \"message\": \"Item not found.\" }"
        }
    }
}

PUT /book/{title}

{
    "title": "Upsert a Book",
    "description": "Update price or create a new book if absent.",
    "method": "PUT",
    "baseUrl": "http://localhost:5000",
    "endpoint": "/book/{title}",
    "headers": [
        { "key": "Content-Type", "value": "application/json", "required": true }
    ],
    "pathParams": [
        { "key": "title", "value": "Book title", "required": true }
    ],
    "bodyType": "json",
    "requestBody": "{\n  \"price\": 25.00,\n  \"store_id\": 2,\n  \"author\": \"John Smith\",\n  \"isbn\": \"XYZ789\",\n  \"release_date\": \"2022-05-05\"\n}",
    "responses": {
        "200": {
            "description": "Book upserted",
            "body": "{ \"title\": \"Title\", \"price\": 25.0, \"author\": \"John Smith\", \"isbn\": \"XYZ789\", \"release_date\": \"2022-05-05\" }"
        }
    }
}

GET /books

{
    "title": "List All Books",
    "description": "Fetch all books in the library.",
    "method": "GET",
    "baseUrl": "http://localhost:5000",
    "endpoint": "/books",
    "headers": [],
    "bodyType": "none",
    "responses": {
        "200": {
            "description": "List of books",
            "body": "{ \"books\": [ { ... }, { ... } ] }"
        }
    }
}

🏬 Store Resource

The Store resource handles CRUD for bookstores. It returns store details and associated books dynamically.

from flask_restful import Resource
from models.store import StoreModel

class Store(Resource):
    def get(self, name):
        store = StoreModel.find_by_name(name)
        if store:
            return store.json()
        return {'message': 'Store not found'}, 404
    ...
class StoreList(Resource):
    def get(self):
        return {'stores': [s.json() for s in StoreModel.query.all()]}

Derived from resources/store.py .

Endpoints Summary

Endpoint Method Description
/store/{name} GET Retrieve store with its books.
/store/{name} POST Create new store; return 400/500 on error.
/store/{name} DELETE Delete store; no content on success.
/stores GET List all stores.

GET /store/{name}

{
    "title": "Retrieve a Store",
    "description": "Fetch a store by name.",
    "method": "GET",
    "baseUrl": "http://localhost:5000",
    "endpoint": "/store/{name}",
    "headers": [],
    "pathParams": [
        { "key": "name", "value": "Store name", "required": true }
    ],
    "bodyType": "none",
    "responses": {
        "200": {
            "description": "Store found",
            "body": "{ \"name\": \"MyStore\", \"books\": [ ... ] }"
        },
        "404": {
            "description": "Store not found",
            "body": "{ \"message\": \"Store not found\" }"
        }
    }
}

POST /store/{name}

{
    "title": "Create a Store",
    "description": "Add a new store by name.",
    "method": "POST",
    "baseUrl": "http://localhost:5000",
    "endpoint": "/store/{name}",
    "headers": [],
    "pathParams": [
        { "key": "name", "value": "Store name", "required": true }
    ],
    "bodyType": "none",
    "responses": {
        "201": {
            "description": "Store created",
            "body": "{ \"name\": \"NewStore\", \"books\": [] }"
        },
        "400": {
            "description": "Duplicate name",
            "body": "{ \"message\": \"A store with name 'NewStore' already exists.\" }"
        },
        "500": {
            "description": "Creation error",
            "body": "{ \"message\": \"An error occurred creating the store.\" }"
        }
    }
}

DELETE /store/{name}

{
    "title": "Delete a Store",
    "description": "Remove store by name.",
    "method": "DELETE",
    "baseUrl": "http://localhost:5000",
    "endpoint": "/store/{name}",
    "headers": [],
    "pathParams": [
        { "key": "name", "value": "Store name", "required": true }
    ],
    "bodyType": "none",
    "responses": {
        "200": {
            "description": "Store deleted",
            "body": "{ \"message\": \"Store deleted\" }"
        }
    }
}

GET /stores

{
    "title": "List All Stores",
    "description": "Fetch all stores with books.",
    "method": "GET",
    "baseUrl": "http://localhost:5000",
    "endpoint": "/stores",
    "headers": [],
    "bodyType": "none",
    "responses": {
        "200": {
            "description": "List of stores",
            "body": "{ \"stores\": [ { ... }, { ... } ] }"
        }
    }
}

👤 User Registration Resource

The UserRegister resource handles new user signup. It validates input and stores credentials.

from flask_restful import Resource, reqparse
from models.user import UserModel

class UserRegister(Resource):
    parser = reqparse.RequestParser()
    parser.add_argument('username',
        type=str, required=True, help="This field cannot be blank.")
    parser.add_argument('password',
        type=str, required=True, help="This field cannot be blank.")

    def post(self):
        data = UserRegister.parser.parse_args()
        if UserModel.find_by_username(data['username']):
            return {"message": "A user with that username already exists"}, 400
        user = UserModel(data['username'], data['password'])
        user.save_to_db()
        return {"message": "User created successfully."}, 201

Derived from resources/user.py .

POST /register

{
    "title": "Register a User",
    "description": "Create a new user account.",
    "method": "POST",
    "baseUrl": "http://localhost:5000",
    "endpoint": "/register",
    "headers": [
        { "key": "Content-Type", "value": "application/json", "required": true }
    ],
    "bodyType": "json",
    "requestBody": "{\n  \"username\": \"newuser\",\n  \"password\": \"securepass\"\n}",
    "responses": {
        "201": {
            "description": "Registration succeeded",
            "body": "{ \"message\": \"User created successfully.\" }"
        },
        "400": {
            "description": "Username exists",
            "body": "{ \"message\": \"A user with that username already exists\" }"
        }
    }
}

{
    "title": "Key Takeaway",
    "content": "Resource classes cleanly separate request handling from business logic."
}