Flask on steroids
Project description
Flaskteroids
Flaskteroids: A complete, batteries-included Python MVC framework inspired by Ruby on Rails.
Flaskteroids (or Flask on Steroids) is a lightweight yet powerful Python MVC framework that supercharges Flask with a clean, elegant structure. Inspired by the best of Ruby on Rails, it brings clarity and productivity to your web development workflow.
Built on the philosophy of convention over configuration, Flaskteroids helps you move fast, write less code, and stay focused on what matters: building scalable, maintainable applications with confidence.
With a batteries-included approach and carefully chosen core dependencies, Flaskteroids stays lean, fast, and secure — giving you everything you need, and nothing you don’t.
Features
- Full MVC Architecture: Clean separation of concerns with Models, Views, and Controllers.
- Elegant Routing: Intuitive and resourceful routing.
- Built-in ORM: Seamless integration with SQLAlchemy and Alembic for database management and migrations.
- Background Jobs: Integrated with Celery for easy background job processing.
- RESTful by Design: Quickly build API routes with JSON responses.
- Powerful CLI: A rich set of commands for generating models, controllers, mailers, scaffolds, and more.
- Flask Compatibility: Retains the full power of Flask and its rich ecosystem.
Table of Contents
- Installation
- Getting Started
- Your First Feature: A Blog
- Core Concepts
- Security
- Command-Line Interface (CLI)
- Testing
- Contributing
- License
Installation
To get started, install the Flaskteroids package using pip:
pip install flaskteroids
Getting Started
1. Creating a New App
Create a new Flaskteroids application using the flaskteroids new command:
flaskteroids new my_project
cd my_project
This creates a new directory called my_project with a standard application structure.
2. Running the Server
To start the development server, run:
flask run
Now, open your browser and navigate to http://127.0.0.1:5000. You should see the Flaskteroids welcome page!
Your First Feature: A Blog
Let's create a simple blog to see the power of scaffolding.
-
Create a new app: This command will create a new Flaskteroids application in a directory called
my_blog.flaskteroids new my_blog cd my_blog
-
Generate a Post scaffold: This command will create the model, controller, views, and database migration for a
Postresource withtitleandcontentfields.flask generate scaffold Post title:string content:text
-
Run the database migration: Apply the changes to your database schema.
flask db:migrate -
Start the server:
flask run
Now, visit http://1227.0.0.1:5000/posts in your browser. You have a complete set of pages to create, view, update, and delete posts.
Core Concepts
Project Structure
A typical Flaskteroids project follows this structure:
my_project/
├── app/
│ ├── controllers/
│ ├── models/
│ ├── mailers/
│ ├── views/
│ └── jobs/
├── config/
│ └── routes.py
└── run.py
app/controllers: Handle web requests and respond with data or rendered views.app/models: Define your application's data structure and database interactions.app/views: Contain the templates for your application's UI.app/mailers: Handle sending emails.app/jobs: Define background jobs to be run asynchronously.config/routes.py: Define the URL routes for your application.
Routing
Routes are defined in config/routes.py by a register function that receives a router instance. You can define standard routes or use resourceful routing to handle RESTful conventions automatically.
# config/routes.py
def register(router):
# A standard route
router.get("/", to="welcome#index")
# Resourceful routes for a 'posts' controller
router.resources("posts")
Controllers
Controllers handle the logic for incoming requests. Actions are methods within a controller class that set instance variables for the view. Rendering is handled automatically.
# app/controllers/posts_controller.py
from flaskteroids import params
from flaskteroids.controller import ActionController
from app.controllers.application_controller import ApplicationController
from app.models.post import Post
class PostsController(ApplicationController):
def index(self):
self.posts = Post.all()
# Implicitly renders app/views/posts/index.html and
# makes @posts available in the template.
def show(self):
self.post = Post.find(params["id"])
# Implicitly renders app/views/posts/show.html and
# makes @post available in the template.
Controller Callbacks
You can use callbacks to run code before a controller action. The before_action callback is useful for setting up instance variables or performing authentication checks. Callbacks must be defined within a @rules decorator.
from flaskteroids import params
from flaskteroids.actions import before_action
from flaskteroids.rules import rules
from app.controllers.application_controller import ApplicationController
from app.models.post import Post
@rules(
before_action('_set_post', only=['show', 'edit', 'update', 'destroy'])
)
class PostsController(ActionController):
def show(self):
# self.post is already set by the callback
pass
def _set_post(self):
self.post = Post.find(params["id"])
Content Negotiation
Flaskteroids can handle different response formats within a single action using the respond_to block. This is particularly useful for building APIs that serve both HTML and JSON.
from flaskteroids.controller import respond_to
from app.controllers.application_controller import ApplicationController
from app.models.post import Post
class PostsController(ActionController):
def index(self):
self.posts = Post.all()
with respond_to() as format:
format.html(lambda: render('index'))
format.json(lambda: render(json=self.posts))
Models
Models inherit from flaskteroids.model.Model and act as a rich wrapper around your database tables. Database columns are defined during migration and are automatically available as attributes on the model.
The Model class provides a powerful API for associations and data validation.
# app/models/post.py
from flaskteroids.model import Model, validates, belongs_to, has_many
from flaskteroids.rules import rules
@rules(
# --- Associations ---
belongs_to('user'),
has_many('comments'),
# --- Validations ---
validates('title', presence=True, length={'minimum': 5}),
validates('content', presence=True)
)
class Post(Model):
# The database columns (e.g., title, content, user_id) are defined
# in the database migration and automatically mapped to this model.
pass
Views
Views are the user-facing part of your application. Flaskteroids uses Jinja2 for templating, which is the default for Flask. Templates are located in the app/views directory and are automatically rendered by controller actions.
Instance variables set in the controller are available in the corresponding view file.
<!-- app/views/posts/index.html -->
{% extends "layouts/application.html" %}
{% block body %}
<h1>Posts</h1>
<ul>
{% for post in posts %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
{% endblock %}
Mailers
Mailers inherit from ActionMailer and are used to send emails from your application. They work similarly to controllers, with actions that correspond to email templates.
# app/mailers/user_mailer.py
from flaskteroids.mailer import ActionMailer
class UserMailer(ActionMailer):
def welcome_email(self, user):
self.user = user
self.mail(to=user.email, subject="Welcome to My App!")
You can then deliver the email synchronously or asynchronously:
# Deliver now
UserMailer().welcome_email(user).deliver_now()
# Deliver later using a background job
UserMailer().welcome_email(user).deliver_later()
Background Jobs
For long-running tasks, you can use background jobs. Jobs inherit from Job and define a perform method.
# app/jobs/my_job.py
from flaskteroids.jobs.job import Job
class MyJob(Job):
def perform(self, user_id):
# Do some long-running task
print(f"Performing job for user {user_id}")
To enqueue a job, call perform_later:
MyJob().perform_later(user_id=1)
Flash Messaging
Flaskteroids provides a flash object for setting and displaying temporary messages.
In your controller, you can set a message like this:
from flaskteroids.flash import flash
class PostsController(ActionController):
def create(self):
# ... create post
flash['notice'] = "Post was successfully created."
# redirect
Then, in your view, you can display the message:
{% if flash.notice %}
<div class="notice">{{ flash.notice }}</div>
{% endif %}
Handling Forms
Handling user input from forms is a common task in web applications. Flaskteroids provides a cohesive set of tools to build forms, handle submissions securely, and prevent common vulnerabilities.
Building Forms
Flaskteroids provides a simple and powerful way to build forms using the form_with helper and the Form object. The form_with helper can be used with a model object to automatically generate the form's action and method, and it also includes the CSRF token automatically.
Here's an example of how to create a form for a Post model:
<!-- app/views/posts/_form.html -->
{% call(form) form_with(model=post) %}
<div>
{{ form.label('title') }}
{{ form.text_field('title') }}
</div>
<div>
{{ form.label('content') }}
{{ form.text_area('content') }}
</div>
<div>
{{ form.submit('Save') }}
</div>
{% endcall %}
The form object provides a variety of helpers for generating form fields, such as text_field, text_area, password_field, checkbox, and more.
Strong Parameters
To prevent mass assignment vulnerabilities, Flaskteroids uses a technique inspired by Rails' Strong Parameters. The params object allows you to whitelist which parameters are permitted in your controller actions.
This is a security best practice that ensures users cannot update model attributes they are not supposed to, such as an admin flag.
Here's how you can use params.expect to safely handle incoming data. The expect method allows you to define the structure of the expected parameters, including nested objects and lists.
# app/controllers/posts_controller.py
from flaskteroids import params
from flaskteroids.controller import ActionController
from app.models.post import Post
class PostsController(ActionController):
# ...
def create(self):
self.post = Post.new(_post_params())
if self.post.save():
# ... success
else:
# ... error
pass
def update(self):
self.post = Post.find(params['id'])
if self.post.update(_post_params()):
# ... success
else:
# ... error
pass
def _post_params(self):
# Assumes form data is sent as:
# post[title]=...
# post[content]=...
return params.expect(post=['title', 'content'])
In this example, _post_params specifies that the params object must contain a top-level key called post, which should be a dictionary containing only the title and content keys. Any other attributes within the post object will be discarded, and if the post key is missing or the structure is incorrect, an exception will be raised.
CSRF Protection
Flaskteroids automatically includes CSRF (Cross-Site Request Forgery) protection on all non-GET requests. A CSRF token is generated and must be included in your forms. The form_with helper does this automatically.
For manual forms, you can include the token like this:
<form action="/posts" method="post">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<!-- ... form fields -->
</form>
Security
Rate Limiting
You can easily add rate limiting to your controllers to prevent abuse. The rate_limit decorator allows you to specify the maximum number of requests allowed within a given time window.
from flaskteroids.rate_limit import rate_limit
@rate_limit(to=10, within=60) # 10 requests per 60 seconds
class PostsController(ActionController):
# ...
Command-Line Interface (CLI)
Flaskteroids extends the flask CLI with a powerful set of tools to streamline development.
Generators
Use the flask generate command to create various components:
-
Authentication:
flask generate authentication
Sets up a complete authentication system (routes, controllers, views).
-
Controller:
flask generate controller <controller_name> [action1 action2 ...]
Example:
flask generate controller users index show -
Mailer:
flask generate mailer <mailer_name> [action1 action2 ...]
Example:
flask generate mailer UserMailer welcome_email -
Migration:
flask generate migration <migration_name>
-
Model:
flask generate model <model_name> [field1:type ...]
Example:
flask generate model User name:string email:string -
Resource:
flask generate resource <resource_name> [field1:type ...]
Generates a model and a RESTful controller.
-
Scaffold:
flask generate scaffold <scaffold_name> [field1:type ...]
Generates a model, RESTful controller, and views.
License
Flaskteroids is open-source and released under the MIT License.
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
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 flaskteroids-0.1.1.tar.gz.
File metadata
- Download URL: flaskteroids-0.1.1.tar.gz
- Upload date:
- Size: 43.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3bf2f501007315ab33f5ba35490b0e0103a304f90adae4c00ef927e5031ca5b6
|
|
| MD5 |
c9120de56ed669d34bce9bbdf795a708
|
|
| BLAKE2b-256 |
c3e43c73413fc0314c92f1e506671ede9c944cc610398e34f42f99d4a9b03975
|
File details
Details for the file flaskteroids-0.1.1-py3-none-any.whl.
File metadata
- Download URL: flaskteroids-0.1.1-py3-none-any.whl
- Upload date:
- Size: 51.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5495f6a91e3d8256ec96960418186d35229d951e453a39937965aa3a0eaf777d
|
|
| MD5 |
634e012869a1b69762f15848763ba588
|
|
| BLAKE2b-256 |
f419ef91e564fc5d86ce487128cb285a2c22de36c226a2219707ed8d5a2455cc
|