Multi Tenancy With Python and Django

25
Multi-Tenancy With Django Scott Crespo Software Engineer Director, Orlando Data Science [email protected]

description

Multi-Tenancy is a critical component of any Software as a Service (SaaS) application, which enables one application instance to serve multiple organizations, or tenants. This presentation by Scott Crespo covers the basics of multi-tenant architectures, and how to implement multi-tenancy using Python, Django, and the open-source project known as Django Tenant Schemas.

Transcript of Multi Tenancy With Python and Django

Page 1: Multi Tenancy With Python and Django

Multi-Tenancy With Django

Scott CrespoSoftware Engineer

Director, Orlando Data Science

[email protected]

Page 2: Multi Tenancy With Python and Django

1. Multi-Tenant Architectures2. Django Tenant Schemas Explained3. Basic Use + Tips and Tricks

Page 3: Multi Tenancy With Python and Django

Definition

Multi-Tenancy:

A software architecture where a single application instance enables multiple organizations (tenants) to view their data.

*This is a key component of XaaS (i.e. Something as a Service)

Page 4: Multi Tenancy With Python and Django

Architectures

Multi-tenant architectures can be placed on a continuum

SeparateShared

Page 5: Multi Tenancy With Python and Django

Common Approaches to Multi-Tenancy

Page 6: Multi Tenancy With Python and Django

Shared ArchitecutreOne Database + One Schema

One database instance, and one public schema serve all tenants.

Pros Easy to build if data layer is simple Every user on same domain (might be desirable) Only use if a Tenant has exactly one user.

Cons Expensive (Makes lots of calls to db for tenant object) Overly-complex (all tables must relate to tenant) Not Secure Difficult disaster recovery Not future-proof

Page 7: Multi Tenancy With Python and Django

Isolated ArchitectureMultiple Databases

Each tenant has their own database instance

Pros Most Secure Easier disaster recovery Not expensive for compute resources

Cons Difficult to scale Expensive storage resources Difficult to share data across tenants

Page 8: Multi Tenancy With Python and Django

Hybrid ArchitectureOne Database – Multiple SchemasOne database instance for all tenants. Each

tenant gets a dedicated schema.

Shared 'public' schema

Dedicated 'tenant' schema

Page 9: Multi Tenancy With Python and Django

What's a Schema?

Acts as a namespace in Postgres

Adds an additional layer of organization/isolation to the database

(Database → Schema → Table)

ex) SELECT * FROM schema_name.table

When a schema is not specified in the connection or query – only the 'public' schema is accessed

Schemas to be queried can be specified in the app's database connection via 'SEARCH_PATH' parameter

Page 10: Multi Tenancy With Python and Django

One Database – Multiple Schemas

Pros Scalable Cheap Simple Semi-secure Sharable

Cons Difficult disaster

recovery Less-secure than

dedicated db's

Page 11: Multi Tenancy With Python and Django

Django Tenant Schemas

Implements Multi-Schema ApproachRequires PostgreSQL

Installation:$ pip install django-tenant-schemas

Docs:Django-tenant-schemas.readthedocs.org

Page 12: Multi Tenancy With Python and Django

Features

1.Tenant-based Subdomains

2.Postgres Support

Page 13: Multi Tenancy With Python and Django

The Tenant Object

Stored on the 'public' schema

Contains 2 Critical Fields domain_url – the tenant's domain (foo.bar.com) schema_name – the schema where the Tenant's

isolated data is stored (tenant_jw8j23jp)

Page 14: Multi Tenancy With Python and Django

Request Routing

1.User makes a request

2.Middleware looks up tenant object on the public schema and returns schema_nameTenant.objects.get(domain=request.domain).schema_name

3.Tenant_Schema's database wrapper adds schema_name to the connection's SEARCH_PATHcursor.execute('SET search_path = public, schema_name')

4.Subsequent Requests include schema_name in the search path

Page 15: Multi Tenancy With Python and Django
Page 16: Multi Tenancy With Python and Django

Basic UseSettings.py

Specify TENANT and SHARED apps Caution! Don't include new tenant registration on tenants' apps

Use the tenant_schemas postgres backend

Use the tenant schemas middleware

Page 17: Multi Tenancy With Python and Django

Basic usemodels.py

Create a tenant app that contains your tenant model (i.e. organization, company, etc).

Use tenant_schema's mixin

domain_url schema_name

from tenant_schemas.models import TenantMixin

class Company(TenantMixin)company_name =models.CharField(max_length=255L)about = models.TextField(blank=True)auto_create_schema = True

Page 18: Multi Tenancy With Python and Django

The app containing your tenant model should remain in the project's root directory. Otherwise

tenant_schemas can't find it. |-- apps| |-- __init__.py| |-- app1| |-- app2| |-- app3|-- Project| |-- __init__.py| |-- settings.py| |-- settings.pyc| |-- urls.py| `-- wsgi.py|-- manage.py`-- tenant |-- admin.py |-- __init__.py |-- models.py |-- tests.py `-- views.py

* you could try simlinks as a work-around, but not recommended

Page 19: Multi Tenancy With Python and Django

Basic UseCommand Line & DNS

Use tenant_schemas command wrapper for db commands

Use sync_schemas and migrate_schemas

DO NOT use syncdb or migrate

Server & DNS Make sure to use subdomain wildcards

Page 20: Multi Tenancy With Python and Django

Basic UseCustom Commands

Create a 'make_tenants' custom command Must create a public tenant and a

private tenant to complete creation of the database

Page 21: Multi Tenancy With Python and Django

from lawfirm.models import LawFirmfrom django.core.management.base import NoArgsCommandimport osif os.environ['DJANGO_SETTINGS_MODULE'] == 'settings.base': from settings.base import BASE_URLelse: from settings.dev import BASE_URL

class Command(NoArgsCommand):

def handle_noargs(self,**options): # create your public tenant LawFirm(domain_url=BASE_URL, schema_name='public', firm_name='LawCRM', ).save() #test tenant to verify sub-domain routing LawFirm(domain_url='test.'+BASE_URL, schema_name='test', firm_name='Test Firm', ).save()

Custom Command:make_tenants.py

Page 22: Multi Tenancy With Python and Django

Schema Naming Schemes

Auto-generate tenant schema names and enforce uniqueness.

Prefix with 'tenant_'

Append a hash to the end

*Schema name must begin with a letter, $, or underscore

Example Database: public test dev tenant_oi883jso tenant_eug03k2s

* Users do not need to know their schema name!

Page 23: Multi Tenancy With Python and Django

Modify Search Path on the Fly(this took time to figure out)

from django.db import connection

connection.set_tenant(tenant)

# set_tenant() accepts tenant object, NOT# tenant_name!

Page 24: Multi Tenancy With Python and Django

Important Decision

Tenant Model on Public Schema

User Model on Public Schema

Easy Less Secure User More Portable

Tenant Model on Public Schema

User Model on Private Schema

Not so easy More secure User Less Portable

VS

Page 25: Multi Tenancy With Python and Django

Thanks!

Scott Crespo

[email protected]