Skip to content

django-superapp/django-superapp-multi-tenant

Repository files navigation

Django SuperApp - Multi Tenant

Getting Started

  1. Setup the project using the instructions from https://django-superapp.bringes.io/
  2. Setup multi_tenant app using the below instructions:
cd my_superapp;
cd superapp/apps;
django_superapp bootstrap-app \
    --template-repo https://github.com/django-superapp/django-superapp-multi-tenant ./multi_tenant;
cd ../../;

Configuration

  1. Make sure to define main_settings['TENANT_MODEL'] = 'my_org_app.Organization' in your settings.py file.
  2. Update your models.py as follow
# my_org_app/models/organization.py
from django.db import models
from superapp.apps.multi_tenant.models import AppTenantModel
from django.utils.translation import gettext_lazy as _

class Organization(AppTenantModel):
    name = models.CharField(_("Name"), max_length=255)

    class TenantMeta:
        tenant_field_name = "id"

    @classmethod
    def get_tenants_for_user(cls, user):
        """
        Check if the user can access this tenant model instance.
        This method should be overridden in subclasses to implement
        specific access control logic.
        """
        if user.is_superuser:
            # If the user is a superuser, they can access all tenants
            return cls.all_objects.all()

        return cls.all_objects.filter(users__user=user, users__role="admin", users__is_active=True)

    def __str__(self):
        return self.name

# my_org_app/models/organization_user.py
from django.conf import settings
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_multitenant.fields import TenantForeignKey

from superapp.apps.easywindow.models.organization import Organization
from superapp.apps.multi_tenant.models import AppAwareTenantModel

class OrganizationUser(AppAwareTenantModel):
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='organization_users',
        null=True,
        blank=True,
    )
    organization = TenantForeignKey(Organization, on_delete=models.CASCADE, related_name='users')
    role = models.CharField(_("Role"), choices=[], max_length=100)

    is_active = models.BooleanField(_("Is active"), default=True)

    class TenantMeta:
        tenant_field_name = "organization_id"

    class Meta:
        verbose_name = _("Organization User")
        verbose_name_plural = _("Organization Users")
        unique_together = ["organization", "user"]

    def __str__(self):
        return f"{self.user} - {self.organization}"


# my_org_app/models/organization_products.py    
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_multitenant.fields import TenantForeignKey
from superapp.apps.easywindow.models.organization import Organization
from superapp.apps.multi_tenant.models import AppAwareTenantModel


class OrganizationProduct(AppAwareTenantModel):
    organization = TenantForeignKey(Organization, on_delete=models.CASCADE, related_name='profiles')
    name = models.CharField(_("Name"), max_length=255)

    class TenantMeta:
        tenant_field_name = "organization_id"

    class Meta:
        unique_together = ['id','organization',]
        ordering = ['organization', 'order', 'profile__name']
        verbose_name = _("Organization Product")
        verbose_name_plural = _("Organization Products")

    def __str__(self):
        return self.name

Useful commands

  • python manage.py tenant_dumpdata --tenant <tenant_pk> --output <filename>.json app_name.model_name
  • python manage.py tenant_loaddata --tenant <tenant_pk> <filename>.json (obs, if <tenant_pk> is different from the one in the json file, all the fixtures will be imported in the specified tenant)

Documentation

For more information please check out the following documentation:

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

No packages published