Skip to main content

FastAPI CLI Library

Project description

MakeFast - FastAPI CLI Manager

Python 3.8+ License: MIT Version

Welcome to MakeFast, a FastAPI CLI library designed to streamline your development workflow — inspired by Laravel's elegant developer experience. With MakeFast, you can scaffold routes, models, requests, resources, migrations, and more, so you can focus on writing high-quality business logic.

Table of Contents

Installation

To install MakeFast, simply run the following command in your terminal:

pip install makefast

After installation, run this command to generate the project template:

makefast init

Install the project dependencies:

pip install -r requirements.txt

Run the development server:

uvicorn main:app --port 8000 --reload

Commands

Project Creation

Command Description Options
makefast init Initializes a new project

Route Generation

Command Description Options
makefast create-route ROUTE_NAME Generates a new route --model MODEL_NAME, --request_scheme REQUEST_NAME, --response_scheme RESPONSE_NAME

Model Generation

Command Description Options
makefast create-model MODEL_NAME Generates a new model --table TABLE_NAME, --collection COLLECTION_NAME

Schema Generation

Command Description Options
makefast create-schema SCHEMA_NAME Generates a new schema

Enum Generation

Command Description Options
makefast create-enum ENUM_NAME Generates a new enum --type str

Request Generation

Generates a Laravel-style FormRequest validation class under app/requests/.

Command Description Options
makefast create_request REQUEST_NAME Generates a new form request class
makefast create_request StoreUserRequest
# → app/requests/store_user_request.py

Resource Generation

Generates a Laravel-style Resource or ResourceCollection class under app/resources/.

Command Description Options
makefast create_resource RESOURCE_NAME Generates a new API resource class
makefast create_resource RESOURCE_NAME -c Also generates a ResourceCollection --collection / -c
makefast create_resource User
# → app/resources/user.py

makefast create_resource User --collection
# → app/resources/user.py + app/resources/user_collection.py

Migration Generation

Command Description
makefast create_migration MIGRATION_NAME Generates a new migration
makefast migrate Runs all pending migrations

Form Requests

Form Requests provide a clean, reusable way to validate incoming HTTP data — just like Laravel's FormRequest.

Defining Rules

# app/requests/store_user_request.py
from makefast.http import FormRequest
from typing import Any, Dict

class StoreUserRequest(FormRequest):

    def authorize(self) -> bool:
        # Return False to reject unauthorized requests (raises 403)
        return True

    def rules(self) -> Dict[str, Any]:
        return {
            "name":     ["required", "string", "min:2", "max:100"],
            "email":    ["required", "email"],
            "password": ["required", "string", "min:8", "confirmed"],
            "age":      ["nullable", "integer", "min:0"],
            "role":     ["required", "in:admin,user,guest"],
        }

Available Rules

Rule Example Description
required "required" Field must be present and non-empty
nullable "nullable" Field may be absent or None
string "string" Must be a str
integer / int "integer" Must be an int
numeric "numeric" Must be int or float
boolean "boolean" Must be bool
email "email" Must match a valid email pattern
min:<n> "min:3" Min length (strings) or min value (numbers)
max:<n> "max:255" Max length (strings) or max value (numbers)
in:<a,b,c> "in:admin,user" Value must be one of the listed options
not_in:<a,b,c> "not_in:banned" Value must NOT be one of the listed options
regex:<pattern> "regex:^[A-Z]" Must match the given regex pattern
confirmed "confirmed" Must equal {field}_confirmation in the request body

Custom Messages

def messages(self) -> Dict[str, str]:
    return {
        "name.required":  "Please tell us your name.",
        "email.email":    "Please use a valid email address.",
        "password.min":   "Password must be at least 8 characters.",
    }

Using in Routes

Use the request class as a FastAPI dependency via Depends:

from fastapi import APIRouter, Depends
from app.requests.store_user_request import StoreUserRequest

router = APIRouter()

@router.post("/users")
async def store(req: StoreUserRequest = Depends(StoreUserRequest.from_request)):
    # req.validated() → only fields that passed validation
    data = req.validated()
    user = await User.create(**data)
    return {"message": "User created", "user": user}

If validation fails, a 422 Unprocessable Entity response is returned automatically with detailed error messages. If authorize() returns False, a 403 Forbidden is raised.


API Resources

Resources provide a consistent way to transform your model data before returning it from your routes — like Laravel's API Resources.

Single Resource

# app/resources/user.py
from makefast.http import Resource
from typing import Any, Dict

class UserResource(Resource):
    def to_dict(self) -> Dict[str, Any]:
        return {
            "id":         self.data["id"],
            "name":       self.data["name"],
            "email":      self.data["email"],
            "created_at": str(self.data.get("created_at", "")),
        }

Use in a route:

from app.resources.user import UserResource

@router.get("/users/{id}")
async def show(id: int):
    user = await User.find(id)
    return UserResource(user).response()
    # → {"data": {"id": 1, "name": "Alice", "email": "..."}}

Fluent modifiers:

# Remove the "data" wrapper
UserResource(user).without_wrapping().response()
# → {"id": 1, "name": "Alice", ...}

# Use a custom wrapper key
UserResource(user).wrap("user").response()
# → {"user": {"id": 1, ...}}

# Attach extra metadata
UserResource(user).with_meta({"token": jwt_token}).response()
# → {"data": {...}, "token": "..."}

Resource Collection

# app/resources/user_collection.py
from makefast.http import ResourceCollection
from app.resources.user import UserResource

class UserCollection(ResourceCollection):
    resource_class = UserResource

Use in a route:

from app.resources.user_collection import UserCollection

@router.get("/users")
async def index():
    users = await User.all()
    return UserCollection(users).response()
    # → {"data": [{...}, {...}]}

Inline factory (no subclassing needed):

from makefast.http import ResourceCollection
from app.resources.user import UserResource

return ResourceCollection.of(UserResource, users).response()

Pagination with Resources

@router.get("/users")
async def index(page: int = 1):
    # Paginate with conditions using QueryBuilder
    result = await User.query().where("active", 1).order_by("name").paginate(page=page, per_page=15)

    return UserCollection(result["data"]).with_pagination(result).response()

Response shape:

{
  "data": [...],
  "pagination": {
    "total": 42,
    "per_page": 15,
    "current_page": 1,
    "last_page": 3,
    "from": 1,
    "to": 15
  }
}

Database Configuration

MakeFast provides the easiest way to configure and use a database. By default, MakeFast supports MySQL and MongoDB.

MySQL

Add the following lines to main.py:

from fastapi import FastAPI
from makefast.database import MySQLDatabaseInit

app = FastAPI()

MySQLDatabaseInit.init(app)

Configure your .env file:

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=your_database
DB_USERNAME=your_username
DB_PASSWORD=your_password

MongoDB

Add the following lines to main.py:

from fastapi import FastAPI
from makefast.database import MongoDBDatabaseInit

app = FastAPI()

MongoDBDatabaseInit.init(app)

Database CRUD operations

MakeFast offers built-in methods for CRUD operations. First, create a model that corresponds to your MySQL table or MongoDB collection.

Create

from app.models import User

user = await User.create(**{
    "username": "usertest",
    "email": "test@example.com",
    "password": "test123",
})

Update

await User.update(45, **{
    "name": "New name"
})

Find one

await User.find(45)
await User.find_or_fail(45)  # raises 404 if not found

Find all

await User.all()

Delete

await User.delete(45)

Advanced Query Builder

MakeFast's MySQL integration includes a powerful QueryBuilder for building advanced queries with full validation and SQL injection protection.

Filtering

# WHERE username = 'john'
users = await User.query().where("username", "john").get()

# WHERE age > 18 AND status = 'active'
users = await User.query().where("age", ">", 18).where("status", "active").get()

# WHERE IN / NOT IN
users = await User.query().where_in("status", ["active", "pending"]).get()

# WHERE IS NULL / IS NOT NULL
users = await User.query().where_null("deleted_at").get()

# WHERE BETWEEN
users = await User.query().where_between("age", 18, 65).get()

# WHERE LIKE
users = await User.query().where_like("email", "%@gmail.com").get()

# OR WHERE
users = await User.query().where("role", "admin").or_where("role", "moderator").get()

Joins

# INNER JOIN
results = await User.query().join("profiles", "users.id", "profiles.user_id").get()

# LEFT JOIN
results = await User.query().left_join("orders", "users.id", "orders.user_id").get()

# RIGHT JOIN
results = await User.query().right_join("departments", "users.dept_id", "departments.id").get()

Select Specific Columns

users = await User.query().select("id", "username", "email").get()

# With alias
users = await User.query().select_raw("users.id as user_id", "profiles.bio as profile_bio").get()

Ordering, Limit & Offset

users = await User.query().order_by("created_at", "DESC").limit(10).offset(20).get()

Group By

results = await User.query().select("role").group_by("role").get()

First / First Or Fail

user = await User.query().where("username", "john").first()
user = await User.query().where("username", "john").first_or_fail()  # raises 404

Pagination (Chained)

Paginate any query, including those with joins, filters, and ordering:

result = await User.query() \
    .where("active", 1) \
    .order_by("created_at", "DESC") \
    .paginate(page=1, per_page=15)

# result = {
#   "data": [...],
#   "total": 42,
#   "per_page": 15,
#   "current_page": 1,
#   "last_page": 3,
#   "from": 1,
#   "to": 15
# }

Simple Pagination (Class-level)

result = await User.paginate(page=2, per_page=20)

Exists Check

already_taken = await User.query().where("email", email).exists()
if already_taken:
    raise HTTPException(400, "Email already registered")

Chained Update & Delete

# Update matching records
rows_updated = await User.query().where("status", "inactive").update(status="archived")

# Delete matching records (WHERE is required for safety)
rows_deleted = await User.query().where("deleted_at", "<", cutoff_date).delete()

Aggregations

Built-in aggregation helpers on both the model and the query builder:

total_users = await User.count()
max_age    = await User.max("age")
min_age    = await User.min("age")
avg_age    = await User.avg("age")
total_bal  = await User.sum("balance")

# With conditions
active_count = await User.query().where("active", 1).count()

Bulk Operations

Bulk Create

users = await User.bulk_create([
    {"username": "alice", "email": "alice@example.com"},
    {"username": "bob",   "email": "bob@example.com"},
])

Get or Create

user, created = await User.get_or_create(
    username="john",
    defaults={"email": "john@example.com"}
)

Update or Create

user, created = await User.update_or_create(
    username="john",
    defaults={"email": "newjohn@example.com"}
)

Safe Raw Queries

MakeFast allows raw SQL execution with strict validation and safety:

results = await User.safe_raw_query(
    "SELECT id, username FROM users WHERE status = %s",
    params=("active",)
)

By default, only SELECT queries are allowed unless you explicitly pass allowed_operations:

results = await User.safe_raw_query(
    "UPDATE users SET status = %s WHERE id = %s",
    params=("active", 1),
    allowed_operations={"UPDATE"}
)

Project Structure

After running makefast init, your project will have the following structure:

app/
├── dependencies/
│   └── response_handler.py
├── enums/
├── migrations/
├── models/
├── requests/          ← Form Request classes
├── resources/         ← API Resource & Collection classes
├── routes/
└── schemas/
.makefast/
└── executed_migrations.txt
main.py
.env
requirements.txt

Contributing

Contributions are welcome! To contribute to MakeFast, follow these steps:

  1. Fork the repository
  2. Create a new branch
  3. Make changes and commit them
  4. Create a pull request

License

MakeFast is licensed under the MIT License. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

makefast-2.3.0.tar.gz (86.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

makefast-2.3.0-py3-none-any.whl (87.7 kB view details)

Uploaded Python 3

File details

Details for the file makefast-2.3.0.tar.gz.

File metadata

  • Download URL: makefast-2.3.0.tar.gz
  • Upload date:
  • Size: 86.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.3

File hashes

Hashes for makefast-2.3.0.tar.gz
Algorithm Hash digest
SHA256 b957ac74bb921fcb30cb2d7d8c4dd9f8fe349e8cc91a594eef4dc841b43339a2
MD5 4f4fa07ddd5b540635c5c96c1e35695b
BLAKE2b-256 17534869b96d0db1ee5606bed999c4dce52cc68fa6bd9dfab1df572c488ce5dd

See more details on using hashes here.

File details

Details for the file makefast-2.3.0-py3-none-any.whl.

File metadata

  • Download URL: makefast-2.3.0-py3-none-any.whl
  • Upload date:
  • Size: 87.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.3

File hashes

Hashes for makefast-2.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b7bdd55cfa5b4655b54f8c086f5d3a64e86eaa32c92c02f2c111fb95bb70312c
MD5 2e6b30014f2c25c32bfa9f84be3e9b2e
BLAKE2b-256 ec7c11a28b58df9aae75b045f9683f0acae8a31580aece46d6c98bc167c2631c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page