Name: django-multitenant
Owner: Citus Data
Description: Python/Django support for distributed multi-tenant databases like Postgres+Citus
Created: 2017-05-19 05:23:40.0
Updated: 2018-01-11 12:33:37.0
Pushed: 2018-01-03 19:42:59.0
Homepage: null
Size: 46
Language: Python
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
Python/Django support for distributed multi-tenant databases like Postgres+Citus
Enables easy scale-out by adding the tenant context to your queries, enabling the database (e.g. Citus) to efficiently route queries to the right database node.
There are architecures for building multi-tenant databases viz. Create one database per tenant, Create one schema per tenant and Have all tenants share the same table(s). This library is based on the 3rd design i.e Have all tenants share the same table(s), it assumes that all the tenant relates models/tables have a tenant_id column for representing a tenant.
The following link talks more about the trade-offs on when and how to choose the right architecture for your multi-tenat database:
https://www.citusdata.com/blog/2016/10/03/designing-your-saas-database-for-high-scalability/
Other useful links on multi-tenancy:
Tested with django 1.10 or higher.
rt django_multitenant
django_multitenant import *
Ex: class Product(TenantModel):
Ex: tenant_id='store_id'
s Product(TenantModel):
store = models.ForeignKey(Store)
tenant_id='store_id'
name = models.CharField(max_length=255)
description = models.TextField()
class Meta(object):
unique_together = ["id", "store"]
s Purchase(TenantModel):
ore = models.ForeignKey(Store)
nant_id='store_id'
oduct_purchased = TenantForeignKey(Product)
s SetCurrentTenantFromUser(object):
def process_request(self, request):
if not hasattr(self, 'authenticator'):
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
self.authenticator = JSONWebTokenAuthentication()
try:
user, _ = self.authenticator.authenticate(request)
except:
# TODO: handle failure
return
try:
#Assuming your app has a function to get the tenant associated for a user
current_tenant = get_tenant_for_user(user)
except:
# TODO: handle failure
return
set_current_tenant(current_tenant)
def process_response(self, request, response):
set_current_tenant(None)
return response
DDLEWARE_CLASSES = (
'our_app.utils.multitenancy.SetCurrentTenantFromUser',
application_function:
# current_tenant can be stored as a SESSION variable when a user logs in.
# This should be done by the app
t = current_tenant
#set the tenant
set_current_tenant(t);
#Django ORM API calls;
#Command 1;
#Command 2;
#Command 3;
#Command 4;
#Command 5;
select_related()
.ore.objects.all()[0]
current_tenant(s)
the below API calls would add suitable tenant filters.
ple get_queryset()
uct.objects.get_queryset()
ple join
hase.objects.filter(id=1).filter(store__name='The Awesome Store').filter(product__description='All products are awesome')
ate
hase.objects.filter(id=1).update(id=1)
e
oduct(8,1,'Awesome Shoe','These shoes are awesome')
ve()
ple aggregates
uct.objects.count()
uct.objects.filter(store__name='The Awesome Store').count()
queries
uct.objects.filter(name='Awesome Shoe');
hase.objects.filter(product__in=p);
This library uses similar logic of setting/getting tenant object as in django-simple-multitenant. We thank the authors for their efforts.