Easy to create applications that use tenants in django
Project description
easy-tenants
This is a Django app for managing multiple tenants on the same project instance using a shared approach.
Background
There are typically three solutions for solving the multitenancy problem:
- Isolated Approach: Separate Databases. Each tenant has it’s own database.
- Semi Isolated Approach: Shared Database, Separate Schemas. One database for all tenants, but one schema per tenant.
- 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 third approach, which in our opinion, is the best solution for a large amount of tenants.
For more information: Building Multi Tenant Applications with Django
Below is a demonstration of the features in each approach for an application with 5000 tenants.
Approach | Number of DB | Number of Schemas | Django migration time | Public access |
---|---|---|---|---|
Isolated | 5000 | 5000 | slow (1/DB) | No |
Semi Isolated | 1 | 5000 | slow (1/Schema) | Yes |
Shared | 1 | 1 | fast (1) | Yes |
Installation
Assuming you have django installed, the first step is to install django-easy-tenants
.
python -m pip install django-easy-tenants
Now you can import the tenancy module in your Django project.
Setup
It is recommended to install this app at the beginning of a project. In an existing project, depending on the structure of the models, the data migration can be hard.
Add easy_tenants
to your INSTALLED_APPS
on settings.py
.
settings.py
INSTALLED_APPS = [
...,
'easy_tenants',
]
Create a model which will be the tenant of the application.
yourapp/models.py
from django.db import models
class Customer(models.Model):
...
settings.py
EASY_TENANTS_TENANT_MODEL = "yourapp.Customer"
Your models, which must have isolated data per tenant, we need to add the foreign field from the Customer model.
and objects need to be replaced with TenantManager()
.
from django.db import models
from easy_tenants.models import TenantManager
class Product(models.Model):
tenant = models.ForeignKey(Customer, on_delete=models.CASCADE, editable=False)
name = models.CharField(max_length=10)
objects = TenantManager()
If you prefer you can use TenantAwareAbstract
to implement the save method for you,
so when saving an object the tenant will be automatically defined.
class Product(TenantAwareAbstract):
tenant = models.ForeignKey(Customer, on_delete=models.CASCADE, editable=False)
name = models.CharField(max_length=10)
objects = TenantManager()
If your foreign field has a name other than tenant
you can change it with a settings. (default is "tenant"
)
# models.py
class Product(TenantAwareAbstract):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, editable=False)
name = models.CharField(max_length=10)
objects = TenantManager()
# settings.py
EASY_TENANTS_TENANT_FIELD = "customer"
To obtain the data for each tenant, it is necessary to define which tenant will be used:
from easy_tenants import tenant_context
with tenant_context(customer):
Product.objects.all() # filter by customer
To define the tenant to be used, this will depend on the business rule used. Here is an example for creating middleware that defines a tenant:
from django.http import HttpResponse
from easy_tenants import tenant_context
class TenantMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
customer = get_customer_by_request(request)
if not customer:
return HttpResponse("Select tenant")
with tenant_context(customer):
return self.get_response(request)
If you want to separate the upload files by tenant, you need to change the DEFAULT_FILE_STORAGE
configuration (only available for local files).
DEFAULT_FILE_STORAGE = 'easy_tenants.storage.TenantFileSystemStorage'
Running the example project
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
Access the page /admin/
, create a Customer
.
Motivation
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file django_easy_tenants-0.9.2.tar.gz
.
File metadata
- Download URL: django_easy_tenants-0.9.2.tar.gz
- Upload date:
- Size: 8.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.7.1 CPython/3.11.1 Linux/6.7.9-100.fc38.x86_64
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2320dcf648ba6891cfe176536625c766408234bc83228bcb84d3b48453424726 |
|
MD5 | 9fca42b7ddfe9e6963428db2b472a12f |
|
BLAKE2b-256 | 29d6b1055ecc3b64ce2cd87f22d296c60399692c47321c6163eb61ed364dfd6e |
File details
Details for the file django_easy_tenants-0.9.2-py3-none-any.whl
.
File metadata
- Download URL: django_easy_tenants-0.9.2-py3-none-any.whl
- Upload date:
- Size: 8.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.7.1 CPython/3.11.1 Linux/6.7.9-100.fc38.x86_64
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 71e645dc9e5b509ce7ff6025142cafd56793f287537f736e73723ee4fc0004a9 |
|
MD5 | 40b431e36366f9797dd12752584136a3 |
|
BLAKE2b-256 | 0046cac26f9c2f6a75751bfd5e539b5b2d17b7f4653cd62e16cc59106ca6b405 |