Enhanced Flask-Smorest blueprints with automatic CRUD operations
Project description
Flask-More-Smorest
Flask-More-Smorest extends Flask-Smorest with a number of enhancements and goodies, with the sole goal of drastically reducing boilerplate and complexity when creating a new REST API with Flask and Flask-Smorest.
Links:
- 📦 PyPI: https://pypi.org/project/flask-more-smorest/
- 📚 Documentation: https://flask-more-smorest.readthedocs.io/
- 🐙 GitHub: https://github.com/qualisero/flask-more-smorest
Highlights
- Automatic CRUD endpoints with filtering and pagination
- SQLAlchemy base model with auto-generated Marshmallow schemas
- Built-in user authentication with JWT and role-based permissions
- UserBlueprint for instant login/profile endpoints
- Resource-based permission management
- Health check endpoint for load balancers and monitoring
- RFC 7807 error responses for standardized error handling
- SQLAlchemy performance monitoring for identifying slow queries
Quick Start
from flask import Flask
from flask_more_smorest import BaseModel, CRUDBlueprint, init_db
from flask_more_smorest.perms import Api
from flask_more_smorest.sqla import db
from sqlalchemy.orm import Mapped, mapped_column
app = Flask(__name__)
app.config.update(
API_TITLE="Example API",
API_VERSION="v1",
OPENAPI_VERSION="3.0.2",
SQLALCHEMY_DATABASE_URI="sqlite:///example.db",
SECRET_KEY="change-me",
JWT_SECRET_KEY="change-me-too",
)
# Define your model
class Critter(BaseModel):
name: Mapped[str] = mapped_column(db.String(100))
species: Mapped[str] = mapped_column(db.String(50))
cuteness_level: Mapped[int] = mapped_column(db.Integer, default=10)
init_db(app) # sets up SQLAlchemy
api = Api(app) # registers JWT + permission hooks
# Create CRUD blueprint using model class directly
critters = CRUDBlueprint(
"critters",
__name__,
model=Critter, # Use class (preferred over string)
schema=Critter.Schema, # Auto-generated schema
url_prefix="/api/critters/",
)
api.register_blueprint(critters)
This automatically creates RESTful endpoints: GET /api/critters/, GET /api/critters/<id>, POST /api/critters/, PATCH /api/critters/<id>, DELETE /api/critters/<id>, plus automatic filtering (?created_at__from=..., ?species=...) and a health check endpoint at /health.
Controlling endpoints
By default, all CRUD methods are enabled. Control which endpoints are generated:
from flask_more_smorest.crud.crud_blueprint import CRUDMethod
# Enable only specific methods
read_only = CRUDBlueprint(
"critters",
__name__,
model=Critter,
schema=Critter.Schema,
methods=[CRUDMethod.INDEX, CRUDMethod.GET], # Only list and get
)
# Disable specific methods
no_delete = CRUDBlueprint(
"critters",
__name__,
model=Critter,
schema=Critter.Schema,
skip_methods=[CRUDMethod.DELETE], # All except delete
)
For advanced configuration (custom schemas, admin-only endpoints, etc.), see the full documentation.
Working with models
Use BaseModel for simple models with UUID keys, timestamp tracking, and auto-generated Marshmallow schemas:
from flask_more_smorest import BaseModel
from flask_more_smorest.sqla import db
from sqlalchemy.orm import Mapped, mapped_column
class Critter(BaseModel):
name: Mapped[str] = mapped_column(db.String(100), nullable=False)
species: Mapped[str] = mapped_column(db.String(50), nullable=False)
cuteness_level: Mapped[int] = mapped_column(db.Integer, default=10)
Auto-generated schema: Critter.Schema is automatically created with all fields. Use it directly in blueprints—no need to define custom schemas unless you need special validation.
Adding permission checks
Use BasePermsModel when you need permission hooks:
from flask_more_smorest.perms import BasePermsModel
from flask_more_smorest.sqla import db
from sqlalchemy.orm import Mapped, mapped_column
class Critter(BasePermsModel):
name: Mapped[str] = mapped_column(db.String(100), nullable=False)
species: Mapped[str] = mapped_column(db.String(50), nullable=False)
def _can_write(self) -> bool:
return self.is_current_user_admin()
def _can_read(self) -> bool:
return True # Anyone can read
BasePermsModel adds _can_read(), _can_write(), and _can_create() hooks that are checked automatically on CRUD operations.
Built-in user authentication
Get instant authentication with UserBlueprint:
from flask_more_smorest import UserBlueprint
# Instant login and profile endpoints
user_bp = UserBlueprint() # Creates /api/users/login/ and /api/users/me/
api.register_blueprint(user_bp)
This provides:
POST /api/users/login/- JWT authenticationGET /api/users/me/- Current user profile- Full CRUD for user management
- Role-based permissions
Extending the User model
Add custom fields by inheriting from User:
from flask_more_smorest import User, UserBlueprint
from flask_more_smorest.sqla import db
from sqlalchemy.orm import Mapped, mapped_column
class Employee(User):
employee_id: Mapped[str] = mapped_column(db.String(32), unique=True)
department: Mapped[str] = mapped_column(db.String(100))
# Use custom user model in blueprint
employee_bp = UserBlueprint(model=Employee, schema=Employee.Schema)
Enable public registration
class PublicUser(User):
PUBLIC_REGISTRATION = True # Allow unauthenticated user creation
public_bp = UserBlueprint(model=PublicUser, schema=PublicUser.Schema)
Production Features
Health Check Endpoint
Built-in health check for load balancers and monitoring systems:
curl http://localhost:5000/health
{
"status": "healthy",
"timestamp": "2026-01-11T08:30:00+00:00",
"version": "0.6.0",
"database": "connected"
}
Configure via HEALTH_ENDPOINT_PATH and HEALTH_ENDPOINT_ENABLED.
RFC 7807 Error Responses
Standardized error format following RFC 7807:
{
"type": "/errors/not_found_error",
"title": "Not Found",
"status": 404,
"detail": "User with id 123 doesn't exist",
"instance": "/api/users/123"
}
Debug information automatically included in debug/testing mode only.
SQLAlchemy Performance Monitoring
Track and log slow queries:
app.config.update(
SQLALCHEMY_PERFORMANCE_MONITORING=True,
SQLALCHEMY_SLOW_QUERY_THRESHOLD=0.5, # Log queries over 500ms
)
Get per-request statistics:
from flask_more_smorest.sqla import get_request_query_stats
@app.after_request
def log_stats(response):
stats = get_request_query_stats()
print(f"Queries: {stats['query_count']}, Time: {stats['total_query_time']:.3f}s")
return response
Learn more
- 📚 Documentation: https://flask-more-smorest.readthedocs.io/
- 📦 PyPI Package: https://pypi.org/project/flask-more-smorest/
- 🔧 API Reference: Full API documentation and guides available in docs
- 💡 Examples: The
tests/directory demonstrates filters, permissions, and pagination end-to-end
Contributing
Contributions and feedback are welcome! See CONTRIBUTING.md for guidelines.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flask_more_smorest-0.6.0.tar.gz.
File metadata
- Download URL: flask_more_smorest-0.6.0.tar.gz
- Upload date:
- Size: 55.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b97e873d28d85346ef54a65ae79a310bf64266f9a781615c59cec1e50f9442ed
|
|
| MD5 |
5c5463deb1f83660882daffcb1f8da5d
|
|
| BLAKE2b-256 |
84a1a4f216ae8208bf7c92638e931c88045057b8acf8fc75ae2e1844e099f461
|
Provenance
The following attestation bundles were made for flask_more_smorest-0.6.0.tar.gz:
Publisher:
ci-cd.yml on qualisero/flask-more-smorest
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
flask_more_smorest-0.6.0.tar.gz -
Subject digest:
b97e873d28d85346ef54a65ae79a310bf64266f9a781615c59cec1e50f9442ed - Sigstore transparency entry: 813578551
- Sigstore integration time:
-
Permalink:
qualisero/flask-more-smorest@65e8d2e992a35ea425c82c4f64848f0ffa9c20c7 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/qualisero
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci-cd.yml@65e8d2e992a35ea425c82c4f64848f0ffa9c20c7 -
Trigger Event:
release
-
Statement type:
File details
Details for the file flask_more_smorest-0.6.0-py3-none-any.whl.
File metadata
- Download URL: flask_more_smorest-0.6.0-py3-none-any.whl
- Upload date:
- Size: 60.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
75589690892499d31076b858215703d32944525ded7e1bffcc4315925101ea04
|
|
| MD5 |
7268dc1440a82115358ae499b56d3fc8
|
|
| BLAKE2b-256 |
7d77db74db8be7448d65aa8a39f83232d9f52f7c207bd096a12ff4f0dbe18f3f
|
Provenance
The following attestation bundles were made for flask_more_smorest-0.6.0-py3-none-any.whl:
Publisher:
ci-cd.yml on qualisero/flask-more-smorest
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
flask_more_smorest-0.6.0-py3-none-any.whl -
Subject digest:
75589690892499d31076b858215703d32944525ded7e1bffcc4315925101ea04 - Sigstore transparency entry: 813578552
- Sigstore integration time:
-
Permalink:
qualisero/flask-more-smorest@65e8d2e992a35ea425c82c4f64848f0ffa9c20c7 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/qualisero
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci-cd.yml@65e8d2e992a35ea425c82c4f64848f0ffa9c20c7 -
Trigger Event:
release
-
Statement type: