Application Architecture β Flask Application Bootstrap (app.py)
The app.py file serves as the entry point and bootstrapper for the entire REST API application. It ties together Flask, Flask-RESTful, Flask-JWT, and SQLAlchemy, configuring extensions, registering resources, and launching the server .
π¦ app.py: The Entry Point
This module:
- Imports core libraries and application modules.
- Configures the Flask app.
- Initializes extensions (
Api,JWT). - Registers RESTful resources.
- Bootstraps the database on first request.
- Runs the development server.
from flask import Flask
from flask_restful import Api
from flask_jwt import JWT
from security import authenticate, identity
from resources.user import UserRegister
from resources.book import Book, BookList
from resources.store import Store, StoreList
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['PROPAGATE_EXCEPTIONS'] = True
app.secret_key = 'SapanCrackle'
api = Api(app)
@app.before_first_request
def create_tables():
db.create_all()
jwt = JWT(app, authenticate, identity) # /auth endpoint
api.add_resource(Store, '/store/<string:name>')
api.add_resource(StoreList, '/stores')
api.add_resource(Book, '/book/<string:title>')
api.add_resource(BookList, '/books')
api.add_resource(UserRegister, '/register')
if __name__ == '__main__':
from db import db
db.init_app(app)
app.run(port=5000, debug=True)
*Source: app.py *
βοΈ Configuration Settings
The application relies on several Flask config keys to manage database and security behavior:
| Key | Value | Purpose |
|---|---|---|
SQLALCHEMY_DATABASE_URI |
sqlite:///data.db |
Uses a local SQLite file data.db |
SQLALCHEMY_TRACK_MODIFICATIONS |
True |
Enables SQLAlchemy change tracking (overhead) |
PROPAGATE_EXCEPTIONS |
True |
Ensures JWT errors bubble up to Flask error handlers |
secret_key |
'SapanCrackle' |
Secures JWT tokens and session cookies |
π Initializing Flask Extensions
- Api(app)
Provides a RESTful layer on top of Flask.
- JWT(app, authenticate, identity)
Adds JWT-based authentication and auto-registers the /auth endpoint .
- @app.before_first_request β create_tables()
Ensures database tables are created on-demand before handling any HTTP request.
{
"title": "First-Request Hook",
"content": "create_tables() runs once before the first API request to set up the database schema."
}
π Resource Registration
Each resource class maps to a specific URL route:
| Resource | Route | Methods |
|---|---|---|
Store |
/store/<string:name> |
GET, POST, DELETE |
StoreList |
/stores |
GET |
Book |
/book/<string:title> |
GET, POST, PUT, DELETE |
BookList |
/books |
GET |
UserRegister |
/register |
POST |
| Auto | /auth |
POST (JWT token) |
{
"title": "Separation of Concerns",
"content": "Resources handle routing and HTTP logic, while models manage data persistence."
}
π Startup Sequence
flowchart LR
A([Start app.py]) --> B[Initialize Flask Application]
B --> C[Load Configuration]
C --> D[Init Api Extension]
D --> E[Setup JWT /auth]
E --> F[Register Resource Routes]
F --> G[Run Development Server]
G --> H{First HTTP Request}
H -->|β| I[create_tables β db.create_all]
H -->|β| G
Sequence of operations during application startup and first request.
π§ Running the Server
- Environment: Python 3.8
- Command:
python app.py
- Server:
- Host:
localhost - Port:
5000 - Mode:
debug=True
API Endpoints
Base URL: http://localhost:5000
POST /auth
{
"title": "Obtain JWT Token",
"description": "Authenticate user and receive a JWT access token.",
"method": "POST",
"baseUrl": "http://localhost:5000",
"endpoint": "/auth",
"headers": [
{
"key": "Content-Type",
"value": "application/json",
"required": true
}
],
"queryParams": [],
"pathParams": [],
"bodyType": "json",
"requestBody": "{\"username\":\"sapan\",\"password\":\"sapan1234\"}",
"formData": [],
"rawBody": "",
"responses": {
"200": {
"description": "Authentication successful",
"body": "{\n \"access_token\": \"<jwt_token>\"\n}"
},
"401": {
"description": "Invalid credentials",
"body": "{\"description\":\"Invalid credentials\",\"error\":\"Unauthorized\"}"
}
}
}
POST /register
{
"title": "User Registration",
"description": "Register a new user account.",
"method": "POST",
"baseUrl": "http://localhost:5000",
"endpoint": "/register",
"headers": [
{
"key": "Content-Type",
"value": "application/json",
"required": true
}
],
"queryParams": [],
"pathParams": [],
"bodyType": "json",
"requestBody": "{\"username\":\"newuser\",\"password\":\"pass123\"}",
"formData": [],
"rawBody": "",
"responses": {
"201": {
"description": "User created successfully",
"body": "{\"message\":\"User created successfully.\"}"
},
"400": {
"description": "Username already exists",
"body": "{\"message\":\"A user with that username already exists\"}"
}
}
}
GET /stores
{
"title": "List Stores",
"description": "Retrieve all stores.",
"method": "GET",
"baseUrl": "http://localhost:5000",
"endpoint": "/stores",
"headers": [],
"queryParams": [],
"pathParams": [],
"bodyType": "none",
"requestBody": "",
"formData": [],
"rawBody": "",
"responses": {
"200": {
"description": "Stores retrieved",
"body": "{\n \"stores\": []\n}"
}
}
}
GET /store/:name
{
"title": "Get Store",
"description": "Fetch a store by name.",
"method": "GET",
"baseUrl": "http://localhost:5000",
"endpoint": "/store/BookHeaven",
"headers": [],
"queryParams": [],
"pathParams": [
{
"key": "name",
"value": "Store name",
"required": true
}
],
"bodyType": "none",
"requestBody": "",
"formData": [],
"rawBody": "",
"responses": {
"200": {
"description": "Store found",
"body": "{\n \"name\":\"BookHeaven\",\n \"books\":[]\n}"
},
"404": {
"description": "Store not found",
"body": "{\"message\":\"Store not found\"}"
}
}
}
POST /store/:name
{
"title": "Create Store",
"description": "Create a new store with the given name.",
"method": "POST",
"baseUrl": "http://localhost:5000",
"endpoint": "/store/BookHeaven",
"headers": [
{
"key": "Authorization",
"value": "JWT <jwt_token>",
"required": true
}
],
"queryParams": [],
"pathParams": [
{
"key": "name",
"value": "Store name",
"required": true
}
],
"bodyType": "none",
"requestBody": "",
"formData": [],
"rawBody": "",
"responses": {
"201": {
"description": "Store created",
"body": "{\n \"name\":\"BookHeaven\",\n \"books\":[]\n}"
},
"400": {
"description": "Store already exists",
"body": "{\"message\":\"A store with name 'BookHeaven' already exists.\"}"
}
}
}
DELETE /store/:name
{
"title": "Delete Store",
"description": "Remove a store by name.",
"method": "DELETE",
"baseUrl": "http://localhost:5000",
"endpoint": "/store/BookHeaven",
"headers": [
{
"key": "Authorization",
"value": "JWT <jwt_token>",
"required": true
}
],
"queryParams": [],
"pathParams": [
{
"key": "name",
"value": "Store name",
"required": true
}
],
"bodyType": "none",
"requestBody": "",
"formData": [],
"rawBody": "",
"responses": {
"200": {
"description": "Store deleted",
"body": "{\"message\":\"Store deleted\"}"
}
}
}
GET /books
{
"title": "List Books",
"description": "Retrieve all books.",
"method": "GET",
"baseUrl": "http://localhost:5000",
"endpoint": "/books",
"headers": [],
"queryParams": [],
"pathParams": [],
"bodyType": "none",
"requestBody": "",
"formData": [],
"rawBody": "",
"responses": {
"200": {
"description": "Books retrieved",
"body": "{\n \"books\": []\n}"
}
}
}
GET /book/:title
{
"title": "Get Book",
"description": "Fetch a book by title.",
"method": "GET",
"baseUrl": "http://localhost:5000",
"endpoint": "/book/Python101",
"headers": [
{
"key": "Authorization",
"value": "JWT <jwt_token>",
"required": true
}
],
"queryParams": [],
"pathParams": [
{
"key": "title",
"value": "Book title",
"required": true
}
],
"bodyType": "none",
"requestBody": "",
"formData": [],
"rawBody": "",
"responses": {
"200": {
"description": "Book found",
"body": "{\n \"title\":\"Python101\",\n \"price\":29.99,\n \"author\":\"Jane Doe\",\n \"isbn\":\"123-4567890123\",\n \"release_date\":\"2021-01-01\"\n}"
},
"404": {
"description": "Book not found",
"body": "{\"message\":\"book not found\"}"
}
}
}
POST /book/:title
{
"title": "Create Book",
"description": "Add a new book with specified title.",
"method": "POST",
"baseUrl": "http://localhost:5000",
"endpoint": "/book/Python101",
"headers": [
{
"key": "Authorization",
"value": "JWT <jwt_token>",
"required": true
},
{
"key": "Content-Type",
"value": "application/json",
"required": true
}
],
"queryParams": [],
"pathParams": [
{
"key": "title",
"value": "Book title",
"required": true
}
],
"bodyType": "json",
"requestBody": "{\"price\":29.99,\"store_id\":1,\"author\":\"Jane Doe\",\"isbn\":\"123-4567890123\",\"release_date\":\"2021-01-01\"}",
"formData": [],
"rawBody": "",
"responses": {
"201": {
"description": "Book created",
"body": "{\n \"title\":\"Python101\",\n \"price\":29.99,\n \"author\":\"Jane Doe\",\n \"isbn\":\"123-4567890123\",\n \"release_date\":\"2021-01-01\"\n}"
},
"400": {
"description": "Book already exists",
"body": "{\"message\":\"An book with title 'Python101' already exists.\"}"
}
}
}
PUT /book/:title
{
"title": "Update or Create Book",
"description": "Modify price or create book if missing.",
"method": "PUT",
"baseUrl": "http://localhost:5000",
"endpoint": "/book/Python101",
"headers": [
{
"key": "Content-Type",
"value": "application/json",
"required": true
}
],
"queryParams": [],
"pathParams": [
{
"key": "title",
"value": "Book title",
"required": true
}
],
"bodyType": "json",
"requestBody": "{\"price\":24.99,\"store_id\":1,\"author\":\"Jane Doe\",\"isbn\":\"123-4567890123\",\"release_date\":\"2021-01-01\"}",
"formData": [],
"rawBody": "",
"responses": {
"200": {
"description": "Book upserted",
"body": "{\n \"title\":\"Python101\",\n \"price\":24.99,\n \"author\":\"Jane Doe\",\n \"isbn\":\"123-4567890123\",\n \"release_date\":\"2021-01-01\"\n}"
}
}
}
DELETE /book/:title
{
"title": "Delete Book",
"description": "Remove a book by title.",
"method": "DELETE",
"baseUrl": "http://localhost:5000",
"endpoint": "/book/Python101",
"headers": [],
"queryParams": [],
"pathParams": [
{
"key": "title",
"value": "Book title",
"required": true
}
],
"bodyType": "none",
"requestBody": "",
"formData": [],
"rawBody": "",
"responses": {
"200": {
"description": "Book deleted",
"body": "{\"message\":\"Item deleted.\"}"
},
"404": {
"description": "Book not found",
"body": "{\"message\":\"Item not found.\"}"
}
}
}
This bootstrap module ensures that the applicationβs core services and endpoints are configured consistently, fostering maintainability and modular growth.