Skip to main content

Melody

Melody is a Python web framework designed to let you build web applications as quickly as possible, with almost no boilerplate.

Melody provides routing, request and response handling, environment variables, a CLI, templates, and a simple database layer out of the box.

You can see some demos here! :)

Example

Code: alt text

Output: alt text

Features

  • Minimal/Almost no boilerplate
  • ASGI based application server
  • Simple Request and Response classes
  • Dynamic routing with slugs
  • HTTP method based routing
  • Jinja2 template rendering
  • Environment variable support
  • Built-in CLI
  • Development server with melody run with hot reload
  • Simple ORM built on top of Peewee
  • SQLite database support
  • Class based database models
  • Automatic JSON responses from Python dictionaries
  • Werkzeug based routing

Installation

Install Melody using pip:

pip install melody-web

The Python package itself is imported as melody.

Creating an Application

A basic Melody application can be structured like this:

my-app/
├── routes.py
├── controllers.py
├── models.py
└── templates/
    └── index.html

You can keep your controllers in a separate file:

# routes.py

from controllers import index, new

routes = {
    '/': index,
    'POST /new': new
}

Or define your controllers directly in routes.py:

def index(request):
    return {
        'success': True
    }

routes = {
    '/': index
}

Running the Application

Start your application with:

melody run

By default, Melody runs the application on port 8000.

You can specify a different port:

melody run --port 3000

This makes it easy to start an application without manually configuring Uvicorn.

Request and Response

Controllers receive a Melody Request object.

A controller can simply return a Python dictionary:

def index(request):
    return {
        'success': True
    }

Melody automatically converts the response into the appropriate HTTP response.

You can also explicitly create a Response:

from melody.response import Response

def index(request):
    return Response({
        'success': True
    })

Responses can also specify status codes, headers, and cookies.

from melody import cookie

def controller(request):
    return Response(
        {'success': True},
        response_type='application/json'
        status=201,
        headers={'id': 'xyz...', ...},
        cookies=[cookie(name='session_id', value='xyz...'), ...]
    )

Routing

Melody uses Werkzeug's routing system internally, allowing dynamic routes and URL parameters.

A simple route:

routes = {
    '/': index
}

HTTP methods can be specified directly:

routes = {
    'GET /users': users,
    'POST /users': create_user
}

If no HTTP method is specified, the route can match requests regardless of their method:

routes = {
    '/users': users
}

Dynamic Routes

Melody supports dynamic URL parameters:

routes = {
    '/users/<int:id>': user
}

The parameter is passed to the controller through the request:

def user(request):
    user_id = request.params['id']

    return {
        'id': user_id
    }

Werkzeug's routing syntax allows different types of converters, such as integers and strings.

Templates

Melody uses Jinja2 as its template engine.

Templates can be rendered using Melody's rendering system:

from melody.render import render

def index(request):
    return render(
        'index.html',
        {
            'name': 'Melody'
        }
    )

A template can then use standard Jinja2 syntax:

<h1>Hello {{ name }}</h1>

Since Melody uses Jinja2, you can use anything that Jinja2 supports.

Environment Variables

Melody provides support for reading environment variables, allowing configuration and secrets to be kept outside your source code.

For example:

DATABASE_URL=...
SECRET_KEY=...

These values can then be accessed from Python.

This is useful for configuration such as:

  • Database credentials
  • API keys
  • Secret keys
  • Application configuration
  • Deployment settings

You can use these by

from melody import env

db_url = env('DATABASE_URL')

Database

Melody includes a simple database abstraction built on top of Peewee.

The goal is to provide a simple interface for common database operations without requiring a large amount of configuration.

A basic model can look like:

from melody.db import Database, Table, CharField

db = Database('sqlite3.db')

class User(Table):
    username = CharField()
    email = CharField(unique=True)

db.register([User])

You can then use the model with Peewee's familiar query API:

user = User.create(
    username='saksham',
    email='saksham@example.com'
)

Querying:

user = User.select().where(
    User.username == 'saksham'
).get()

ORM

Melody's ORM is built completely upon Peewee ORM, thus melody supports everything that peewee supports.

This gives applications access to familiar operations such as:

User.create(...)
User.select()
User.get(...)
User.update(...)
User.delete()

CLI

Melody includes a command line interface for common application tasks.

Start the development server:

melody run

Specify a port:

melody run --port 8080

The CLI is designed to keep application setup and development commands short and simple.

Application Philosophy

Melody is built around one main idea:

Build web applications with as little boilerplate as possible.

A typical Melody controller can be as simple as:

def index(request):
    return 'hello melody'

Combined with:

routes = {
    '/': index
}

and:

melody run

you have a working web application.

Project Structure

A larger application can be organized like this:

my-app/
├── routes.py
├── controllers.py
├── models.py
├── db.py
├── templates/
│   ├── index.html
│   └── users.html
└── .env

Melody does not force a particular project structure, so small applications can remain simple while larger applications can be organized into separate modules.

But all the routes must be defined as routes dictionary in routes.py.

Why Melody?

I built mellody to minimise the amount of code written to make a fully functional web app.

For example, in a controller, when you return a dictionary, melody automatically returns as JSON, a string as plain text, and when you send down html in a string, it automatically detects it, and renders it as html.

Metadata

Release files for melody-web 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for melody-web 0.1.3
File Size Uploaded Provenance Actions
melody_web-0.1.3.tar.gz 10.0 kB Without provenance Details for melody_web-0.1.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for melody-web 0.1.3
File Interpreter ABI Platform Actions
melody_web-0.1.3-py3-none-any.whl Python 3 none any Details for melody_web-0.1.3-py3-none-any.whl

Total release size: 18.8 kB

Release files / melody_web-0.1.3.tar.gz

Download URL melody_web-0.1.3.tar.gz
Size 10.0 kB
Tags Source
SHA-256 checksum
How to use checksums
ae5a8a82d1621e305f1c152518e196500c1d9a0c516157886d78e95aae0cbbc1
BLAKE2b-256 checksum
How to use checksums
c053fde1cd8594293582b420194f80e714d05affd2d63ee3c2b9a143c6bbe245
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.6

Release files / melody_web-0.1.3-py3-none-any.whl

Download URL melody_web-0.1.3-py3-none-any.whl
Size 8.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d61658bbcc3fcfb8d2da14717ab685b56f9120368833c5fa88722ee351f3ae8e
BLAKE2b-256 checksum
How to use checksums
5bc3dced0866e4fc7ef0eb640984c312be697660fe1cb007eac4e71d61f34bd7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.6

Security for melody-web 0.1.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page