Skip to main content

Tenant support for Django using PostgreSQL schemas.

Project description

PyPi version PyPi downloads Python versions Travis CI PostgreSQL

This application enables django powered websites to have multiple tenants via PostgreSQL schemas. A vital feature for every Software-as-a-Service website.

Django provides currently no simple way to support multiple tenants using the same project instance, even when only the data is different. Because we don’t want you running many copies of your project, you’ll be able to have:

  • Multiple customers running on the same instance

  • Shared and Tenant-Specific data

  • Tenant View-Routing

What are schemas

A schema can be seen as a directory in an operating system, each directory (schema) with it’s own set of files (tables and objects). This allows the same table name and objects to be used in different schemas without conflict. For an accurate description on schemas, see PostgreSQL’s official documentation on schemas.

Why schemas

There are typically three solutions for solving the multitenancy problem.

  1. Isolated Approach: Separate Databases. Each tenant has it’s own database.

  2. Semi Isolated Approach: Shared Database, Separate Schemas. One database for all tenants, but one schema per tenant.

  3. Shared Approach: Shared Database, Shared Schema. All tenants share the same database and schema. There is a main tenant-table, where all other tables have a foreign key pointing to.

This application implements the second approach, which in our opinion, represents the ideal compromise between simplicity and performance.

  • Simplicity: barely make any changes to your current code to support multitenancy. Plus, you only manage one database.

  • Performance: make use of shared connections, buffers and memory.

Each solution has it’s up and down sides, for a more in-depth discussion, see Microsoft’s excellent article on Multi-Tenant Data Architecture.

How it works

Tenants are identified via their host name (i.e tenant.domain.com). This information is stored on a table on the public schema. Whenever a request is made, the host name is used to match a tenant in the database. If there’s a match, the search path is updated to use this tenant’s schema. So from now on all queries will take place at the tenant’s schema. For example, suppose you have a tenant customer at http://customer.example.com. Any request incoming at customer.example.com will automatically use customer‘s schema and make the tenant available at the request. If no tenant is found, a 404 error is raised. This also means you should have a tenant for your main domain, typically using the public schema. For more information please read the setup section.

What can this app do?

As many tenants as you want

Each tenant has its data on a specific schema. Use a single project instance to serve as many as you want.

Tenant-specific and shared apps

Tenant-specific apps do not share their data between tenants, but you can also have shared apps where the information is always available and shared between all.

Tenant View-Routing

You can have different views for http://customer.example.com/ and http://example.com/, even though Django only uses the string after the host name to identify which view to serve.

Magic

Everyone loves magic! You’ll be able to have all this barely having to change your code!

Setup & Documentation

This is just a short setup guide, it is strongly recommended that you read the complete version at django-tenant-schemas.readthedocs.io.

Your DATABASE_ENGINE setting needs to be changed to

DATABASES = {
    'default': {
        'ENGINE': 'tenant_schemas.postgresql_backend',
        # ..
    }
}

Add the middleware tenant_schemas.middleware.TenantMiddleware to the top of MIDDLEWARE_CLASSES, so that each request can be set to use the correct schema.

MIDDLEWARE_CLASSES = (
    'tenant_schemas.middleware.TenantMiddleware',
    #...
)

Add tenant_schemas.routers.TenantSyncRouter to your DATABASE_ROUTERS setting, so that the correct apps can be synced, depending on what’s being synced (shared or tenant).

DATABASE_ROUTERS = (
    'tenant_schemas.routers.TenantSyncRouter',
)

Add tenant_schemas to your INSTALLED_APPS.

Create your tenant model

from django.db import models
from tenant_schemas.models import TenantMixin

class Client(TenantMixin):
    name = models.CharField(max_length=100)
    paid_until =  models.DateField()
    on_trial = models.BooleanField()
    created_on = models.DateField(auto_now_add=True)

Define on settings.py which model is your tenant model. Assuming you created Client inside an app named customers, your TENANT_MODEL should look like this:

TENANT_MODEL = "customers.Client" # app.Model

Now run migrate_schemas to sync your apps to the public schema.

python manage.py migrate_schemas --shared

Create your tenants just like a normal django model. Calling save will automatically create and sync/migrate the schema.

from customers.models import Client

# create your public tenant
tenant = Client(domain_url='tenant.my-domain.com',
                schema_name='tenant1',
                name='My First Tenant',
                paid_until='2014-12-05',
                on_trial=True)
tenant.save()

Any request made to tenant.my-domain.com will now automatically set your PostgreSQL’s search_path to tenant1 and public, making shared apps available too. This means that any call to the methods filter, get, save, delete or any other function involving a database connection will now be done at the tenant’s schema, so you shouldn’t need to change anything at your views.

You’re all set, but we have left key details outside of this short tutorial, such as creating the public tenant and configuring shared and tenant specific apps. Complete instructions can be found at django-tenant-schemas.readthedocs.io.

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

django-tenant-schemas-1.10.0.tar.gz (61.1 kB view details)

Uploaded Source

Built Distributions

django_tenant_schemas-1.10.0-py3-none-any.whl (40.3 kB view details)

Uploaded Python 3

django_tenant_schemas-1.10.0-py2-none-any.whl (40.3 kB view details)

Uploaded Python 2

File details

Details for the file django-tenant-schemas-1.10.0.tar.gz.

File metadata

  • Download URL: django-tenant-schemas-1.10.0.tar.gz
  • Upload date:
  • Size: 61.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/2.0.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.5.1 requests-toolbelt/0.9.1 tqdm/4.37.0 CPython/3.7.3

File hashes

Hashes for django-tenant-schemas-1.10.0.tar.gz
Algorithm Hash digest
SHA256 b0a97eccf1b1864ee7dadad1e26b16f2c23ec77e128f5d8407efcde8140962b4
MD5 d619597c97bfaa2d05329d91781f9266
BLAKE2b-256 8ae703c957a876851d267d60d128568c081359b44be5aa06142e86b14471a019

See more details on using hashes here.

File details

Details for the file django_tenant_schemas-1.10.0-py3-none-any.whl.

File metadata

  • Download URL: django_tenant_schemas-1.10.0-py3-none-any.whl
  • Upload date:
  • Size: 40.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/2.0.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.5.1 requests-toolbelt/0.9.1 tqdm/4.37.0 CPython/3.7.3

File hashes

Hashes for django_tenant_schemas-1.10.0-py3-none-any.whl
Algorithm Hash digest
SHA256 10e940f667e41a6bfcab029204218c849836972a75a74aef67c993bf7920ca49
MD5 6a82a04a3210a0d6a8e261e14fe9c34a
BLAKE2b-256 d7a2856ac56a6b2cb2c78506f097ee9288f0b6e47a882eca13b81b2d9a84dfcb

See more details on using hashes here.

File details

Details for the file django_tenant_schemas-1.10.0-py2-none-any.whl.

File metadata

  • Download URL: django_tenant_schemas-1.10.0-py2-none-any.whl
  • Upload date:
  • Size: 40.3 kB
  • Tags: Python 2
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/2.0.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.5.1 requests-toolbelt/0.9.1 tqdm/4.37.0 CPython/3.7.3

File hashes

Hashes for django_tenant_schemas-1.10.0-py2-none-any.whl
Algorithm Hash digest
SHA256 292f59cc36d808a736d6fd4e4ff9deaa1eb8fcf379e4dce6ce36b7a4176862c4
MD5 b4e5fe80f9f5e1f323aa1e7d52b0a81a
BLAKE2b-256 af2f4a0948397f14a9445888eb131718f4fcc7d44d0d2cb8ef420a4ed6da6c4a

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page