PyRails is a lightweight, opinionated, batteries-included Python web framework built on top of FastAPI and MongoEngine.
It is means to provide helpful, lightweight abstractions to enable standard ways of implementing common patters to
prevent the SaaSification of the developer stack.
The goal is to enhance not inhibit.
- Built on top of FastAPI and MongoEngine ODM
- CLI tool for project management and code generation
- Built-in database management (MongoDB)
- Support for both local and Docker-based development
- Environment-specific configurations
- Automatic API documentation
Install PyRails using pip:
pip install pyrails
Create a new PyRails project using the new
command:
pyrails new my_project
cd my_project
This will create a new directory myapp
with the default project structure:
myapp/
├── app/
│ ├── controllers/
│ ├── models/
│ └── __init__.py
├── config/
│ ├── development.py
│ ├── production.py
│ └── __init__.py
├── main.py
├── Dockerfile
└── docker-compose.yml
Start the development server using the run
command:
pyrails run
This will start the development server on http://localhost:8000.
You can also run the service using Docker:
pyrails run --docker
PyRails includes a scaffold generator to quickly create models, controllers, and route definitions for a new resource.
To generate a scaffold for a Post
resource with title
and body
fields:
pyrails generate scaffold Post title:str body:str
This will generate:
app/models/post.py
with aPost
model classapp/controllers/posts_controller.py
with CRUD route handlers- Update
app/controllers/__init__.py
to import the new controller - Update
app/models/__init__.py
to import the new model
You can also generate models and controllers individually.
To generate a Comment
model with post_id
, author
, and content
fields:
pyrails generate model Comment post_id:str author:str content:str
To generate a controller for Auth
routes:
pyrails generate controller Auth
You can also pass in the routes to generate as arguments:
pyrails generate controller Auth post:login post:register
When generating models, you can define relationships between models and specify field options.
- One-to-Many Relationship: Use the
ref:
prefix followed by the related model name.
pyrails generate model Post author:ref:User
This will generate a Post
model with an author
field referencing the User
model.
- Many-to-Many Relationship: Use
list:
andref:
together.
pyrails generate model Student courses:list:ref:Course
This will generate a Student
model with a courses
field that is a list of references to Course
models.
- Optional Field: Append
_
to the field name to mark it as optional.
pyrails generate model User email_:str
This will generate a User
model with an optional email
field.
- Unique Field: Append
^
to the field name to specify it as unique.
pyrails generate model User username^:str
This will generate a User
model with a unique username
field.
- Hashed Field: Use
_hashed:
suffix to store the field as a hashed value.
pyrails generate model User name:str password_hashed:str
This will generate a User
model with a password
field stored as a hashed value.
- Encrypted Field: Use
_encrypted:
suffix to store the field as an encrypted value.
pyrails generate model User name:str email_encrypted:str secret_note_encrypted:str
This will generate a User
model with email
and secret_note
fields stored as encrypted values.
PyRails supports the following field types: str
, int
, float
, bool
, datetime
, date
, dict
, list
.
Lifecycle hooks like before_request
and after_request
can be defined directly in a controller or inherited from a parent controller. Hooks are useful for tasks such as authentication, logging, or cleanup.
admin_controller.py
from pyrails.controllers import Controller, before_request, after_request
from pyrails.exceptions import UnauthorizedError
from pyrails import Request
class AdminController(Controller):
@before_request
async def check_admin(self, request: Request):
is_admin = False # Replace with actual logic
print("Checking admin status... (this will be run before each request)")
if not is_admin:
raise UnauthorizedError(detail="Unauthorized access.")
@after_request
async def cleanup_stuff(self, request: Request):
print("Cleaning up... (this will be run after each request)")
admin_user_controller.py
from app.controllers.admin_controller import AdminController
class AdminUserController(AdminController):
@get('/admin-user/all-users')
async def all_users(self, request):
return {"users": []}
- Hooks like
check_admin
andafter_request
can be defined directly in a controller or inherited from a parent. - In
AdminUserController
, hooks are inherited fromAdminController
and run before and after each request handler.
- If a
before_request
hook raises an exception (e.g.,UnauthorizedError
), the request handler is skipped, but theafter_request
hook still runs.
PyRails provides commands to manage your MongoDB database.
To start a local MongoDB instance for development:
pyrails db up
To stop the local MongoDB instance:
pyrails db down
You can also specify the environment and run MongoDB in a Docker container:
pyrails db up --env production --docker
Environment-specific configuration files are located in the config
directory:
config/development.py
config/production.py
Here you can set your DATABASE_URL
, API keys, and other settings that vary between environments.
Write tests in the tests
directory. You can run your test suite using:
python -m pytest
- API Documentation: http://localhost:8000/docs
- CLI help:
pyrails --help
For guides, tutorials, and detailed API references, check out the PyRails documentation site.
PyRails is open-source software licensed under the MIT license.