Skip to content

apricotdotcool/django-fqq

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

django-fqq

Tests

Generate schema-prefixed table names with the Django ORM.

django-fqq provides a custom database backend that wraps Django's built-in PostgreSQL backend. It overrides quote_name to prepend the active schema to table names — so "my_table" becomes "my_schema"."my_table" automatically. No changes to your models or queries required.

django-fqq does not modify queries if set_schema has not been called or has been set to a falsy value (e.g. None or "").

Installation

pip install django-fqq

Configuration

1. Set the database backend

DATABASES = {
    "default": {
        "ENGINE": "django_fqq.backend",
        "NAME": "your_db",
        # ... other options
    }
}

If you need a custom database backend you can either inherit from django_fqq.backend.base.DatabaseWrapper or set ops_class = DatabaseOperations from django_fqq.backend.operations.DatabaseOperations in your DatabaseWrapper.

2. Add the app

INSTALLED_APPS = [
    # ...
    "django_fqq",
]

3. Configure shared apps (optional)

Apps listed in FQQ_SHARED_APPS will always use the public schema, regardless of the active schema.

FQQ_SHARED_APPS = ["auth", "contenttypes"]

4. Add the middleware (optional)

The middleware provides very basic routing of requests to a specific database schema. For a more robust solution that handles migrations and other functionality, check out django-tenants.

MIDDLEWARE = [
    "django_fqq.middleware.SchemaMiddleware",
    # ...
]

Subclass SchemaMiddleware and override _get_schema(request) to resolve the schema from the request (e.g. from subdomain, header, or URL).

Usage

Setting the schema manually

from django_fqq.schema import set_schema, clear_schema

set_schema("my_schema")
# All queries now target the "my_schema" schema
# ...
clear_schema()

In a middleware or view

from django_fqq.middleware import SchemaMiddleware

class MySchemaMiddleware(SchemaMiddleware):
    def _get_schema(self, request):
        host = request.get_host().split(".")[0]
        return host

Using a context manager

query_schema sets the schema for the duration of a block and restores the previous state on exit.

from django_fqq.schema import query_schema

with query_schema("my_schema"):
    # All queries target "my_schema"
    ...
# Schema is restored to its previous value (or cleared if none was set)

Nesting is supported — each level restores the schema that was active before it:

from django_fqq.schema import set_schema, query_schema

set_schema("schema_a")

with query_schema("schema_b"):
    # queries target "schema_b"
    with query_schema("schema_c"):
        # queries target "schema_c"
        ...
    # back to "schema_b"

# back to "schema_a"

Context-safe

Schema state is stored in a ContextVar, so it's safe across concurrent async requests and threads.

Development

Requires Python 3.12+ and Django 4.2+. Tested against Django 4.2, 5.2, and 6.0.

uv sync
uv run pytest

License

MIT

About

Generate schema-prefixed table names for PostgreSQL with the Django ORM

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages