Skip to main content

Easy to create applications that use tenants in django

Project description

easy-tenants

Tests codecov PyPI Version PyPI downloads

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:

  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 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

django-tenant-schemas

django-tenants

django-scopes

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_easy_tenants-0.9.2.tar.gz (8.1 kB view details)

Uploaded Source

Built Distribution

django_easy_tenants-0.9.2-py3-none-any.whl (8.4 kB view details)

Uploaded Python 3

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

Hashes for django_easy_tenants-0.9.2.tar.gz
Algorithm Hash digest
SHA256 2320dcf648ba6891cfe176536625c766408234bc83228bcb84d3b48453424726
MD5 9fca42b7ddfe9e6963428db2b472a12f
BLAKE2b-256 29d6b1055ecc3b64ce2cd87f22d296c60399692c47321c6163eb61ed364dfd6e

See more details on using hashes here.

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

Hashes for django_easy_tenants-0.9.2-py3-none-any.whl
Algorithm Hash digest
SHA256 71e645dc9e5b509ce7ff6025142cafd56793f287537f736e73723ee4fc0004a9
MD5 40b431e36366f9797dd12752584136a3
BLAKE2b-256 0046cac26f9c2f6a75751bfd5e539b5b2d17b7f4653cd62e16cc59106ca6b405

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