Skip to content

Instantly share code, notes, and snippets.

@codemickeycode
Last active September 7, 2016 01:39
Show Gist options
  • Save codemickeycode/9f2561d658a43ee044bafce2a704dcc9 to your computer and use it in GitHub Desktop.
Save codemickeycode/9f2561d658a43ee044bafce2a704dcc9 to your computer and use it in GitHub Desktop.
Multi-tenancy Implementation for Django

Multi-tenancy Implementation for Django

  • Notes on how to use django-tenants library:
    • Data Architecture
    • Domain setup / URL routing for root and per tenant
    • App structure
    • Limitations

django-tenants

Data Architecture

Shared database, separate schema for each tenant

Migrate commands

./manage.py makemigrations

Public schema

./manage.py migrate_schemas --shared

Tenant schema

./manage.py migrate_schemas --schema=tenant1

Creating a tenant schema - 2 ways

1. Python shell command - create your tenants just like a normal django model. Calling save will automatically create and sync the schema.

from customers.models import Client, Domain

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

2. Via Django Admin

  • on <root domain>/admin, you can add Client and Domain records and it will automically create a schema and setup subdomain url route per tenant

Creating models - how to specify which schema (public or tenant)

Public schema

  • in settings.py, add your public app
SHARED_APPS = (
    'django_tenants',  # mandatory
    'customers', # you must list the app where your tenant model resides in
    # ...
)

  • in <your public app>/models.py,
from django.db import models

from django_tenants.models import TenantMixin, DomainMixin


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)

    # default true, schema will be automatically created and synced when it is saved
    auto_create_schema = True

class Domain(DomainMixin):
    pass

class PublicModel1(TenantMixin):
    pass

Tenant schema

  • in settings.py, add your tenant-specific app
TENANT_APPS = (
    # ...
    # your tenant-specific apps
    'myapp',
    # ...
)
  • in <your tenant app>/models.py
from django.contrib import admin

# Register your models here.

# from customers.models import Client, Domain
from myapp.models import DummyModel, ModelWithFkToPublicUser

@admin.register(DummyModel)
class DummyModelAdmin(admin.ModelAdmin):
    pass

@admin.register(ModelWithFkToPublicUser)
class ModelWithFkToPublicUserAdmin(admin.ModelAdmin):
    pass

Admin and Tenant Superuser

./manage.py create_tenant_superuser --username='admin' --schema=tenant1

Root and Tenant Domain / URL Routing

Shell Command

# Add one or more domains for the tenant
domain = Domain()
domain.domain = 'tenant.my-domain.com'
domain.tenant = tenant
domain.is_primary = True
domain.save()

Update /etc/hosts

127.0.0.1       my-domain.com tenant.my-domain.com tenant2.my-domain.com

Examples:

Limitations

  • You can’t use the normal migration commands
  • Reports - when you need to create a report regarding all the clients/tenants, tenant data will be on separate schemas

Note

  • the django-tenants (for > django 1.8) documentation is not very thorough but it was largely based on django-tenant-schemas (for < django 1.7) so you can still refer to the django-tenant-schemas documentation for instructions on how to use utils etc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment