Installation
Prerequisites
A Django project set up and running.
django-tenantsinstalled and configured. If you haven’t done this yet, refer to the django-tenants documentation for guidance.
Installing django-tenant-users
To install django-tenant-users, use your favorite package manager:
pip install django-tenant-users
Configuring Your Django Project
Modifying the Tenant Model
Your existing TenantModel, which should be configured in
settings.py, needs to be updated to inherit from our TenantBase
instead of TenantMixin.
Here’s an example of how to modify your existing TenantModel:
from tenant_users.tenants.models import TenantBase
class Company(TenantBase):
name = models.CharField(max_length=100)
description = models.TextField(max_length=200)
Creating the User Model
If you haven’t already defined a custom user model in your project,
you’ll need to create one and have it inherit from UserProfile. See
the Django User Model documentation
for more information.
In the example below, we define a TenantUser model within the
users application:
from tenant_users.tenants.models import UserProfile
class TenantUser(UserProfile):
name = models.CharField(max_length=100)
Updating Settings
Add the tenant_users apps to SHARED_APPS and TENANT_APPS.
SHARED_APPS = [
...
"django.contrib.auth",
"django.contrib.contenttypes",
"tenant_users.permissions",
"tenant_users.tenants",
"companies",
"users",
...
]
TENANT_APPS = [
...
"django.contrib.auth",
"django.contrib.contenttypes",
"tenant_users.permissions",
...
]
Using Multi-Type Tenants
If you’re leveraging the Multi-type Tenants feature .. code-block:: python .. code-block:: python
- TENANT_TYPES = {
- “public”: {
- “APPS”: [
“django.contrib.auth”, “django.contrib.contenttypes”, “tenant_users.permissions”, “tenant_users.tenants”, “companies”, “users”, # Add other apps as needed ],
“URLCONF”: “myproject.urls.public”,
},
- “type1”: {
- “APPS”: [
“django.contrib.auth”, “django.contrib.contenttypes”, “tenant_users.permissions”, # Add other apps as needed ], },
# Add other tenant types as needed }
Important
Ensure the app containing your TenantBase (companies) and
TenantUser (users), are only in the SHARED_APPS list.
User Authentication
Switch to the custom authentication backend:
AUTHENTICATION_BACKENDS = ("tenant_users.permissions.backend.UserBackend",)
Tenant Domain
When provisioning new tenants, we need to know what domain to when provisioning new tenants.
TENANT_USERS_DOMAIN = "domain.com"
Custom Auth User Model
Finally, ensure that you define or update the AUTH_USER_MODEL to
point to the model inherting TenantUser.
AUTH_USER_MODEL = "users.TenantUser"
Note
Ensure that settings.TENANT_MODEL is set correctly from your
django-tenant installation.
Optional Settings
Optimizing Tenant Permissions Queries
By default, django-tenant-users uses a simple query to fetch tenant
permissions. However, in scenarios where you need to access related data
(such as profile or groups), this can result in additional
database queries (N+1 query problem).
To optimize these queries, you can configure a custom queryset function
using the TENANT_USERS_PERMS_QUERYSET setting. This allows you to
use Django’s select_related() or prefetch_related() to eagerly
load related data.
Using the Built-in Optimizer
django-tenant-users provides a built-in optimizer that covers most
common use cases:
# settings.py
TENANT_USERS_PERMS_QUERYSET = (
"tenant_users.permissions.utils.get_optimized_tenant_perms_queryset"
)
This built-in optimizer uses select_related("profile") and
prefetch_related("groups") to efficiently load related data.
Creating a Custom Optimizer
If you have specific optimization requirements, you can create your own custom optimizer function:
# myapp/utils.py
from tenant_users.permissions.models import UserTenantPermissions
def get_optimized_perms_queryset():
"""Return a custom optimized queryset for UserTenantPermissions.
Customize this to match your specific needs.
"""
return UserTenantPermissions.objects.select_related(
"profile"
).prefetch_related(
"groups",
"user_permissions"
)
Then configure it in your settings:
# settings.py
TENANT_USERS_PERMS_QUERYSET = "myapp.utils.get_optimized_perms_queryset"
Note
The function should return a QuerySet instance, not a model
instance. The framework will call .get(profile_id=...) on the
returned queryset.
Warning
While this optimization reduces the number of queries when accessing
related data, it does add overhead to the initial permission lookup.
Only use this setting if you regularly need to access related data
(like profile or groups) when working with tenant
permissions.
Tenant Access Middleware
To ensure users have access to the requested tenant, you can add the
TenantAccessMiddleware to your Django project. This middleware
checks if the authenticated user has access to the tenant specified in
the request. If the user does not have access, a 404 error is raised.
Unauthenticated users are allowed to proceed.
1. Add the TenantAccessMiddleware to your MIDDLEWARE setting in
settings.py after Django’s AuthenticationMiddleware:
MIDDLEWARE = [
...
"django.contrib.auth.middleware.AuthenticationMiddleware",
...
"tenant_users.tenants.middleware.TenantAccessMiddleware",
...
]
Optionally, customize the error message by setting
TENANT_USERS_ACCESS_ERROR_MESSAGEin yoursettings.py`:
TENANT_USERS_ACCESS_ERROR_MESSAGE = "Custom access denied message."
Note
To grant a user access to the tenant, use the
tenant.add_user() method to add the
user to the tenant.
Provision Public Tenant
When working with django-tenants, it’s essential to have a public tenant
created using migrate_schemas. If you haven’t set up the public
tenant during the django-tenants installation, no problem.
django-tenant-users provides a utils.create_public_tenant(), which takes care of
this for you.
from tenant_users.tenants.utils import create_public_tenant
create_public_tenant(domain_url="public.domain.com", owner_email="admin@domain.com")
Or, alternatively, use the management command:
manage.py create_public_tenant --domain_url public.domain.com --owner_email admin@domain.com
Fin!
Congratulations on successfully setting up django-tenant-users! With
the installation complete, you’re now equipped to harness the power of
global authentication and authorization for your multi-tenancy Django
projects.
As you move forward, we recommend diving into the following sections to
gain a deeper understanding and make the most of
django-tenant-users:
Using django-tenant-users: Explore how get started with the core functionalities.
Core Concepts: Enhance your understanding of the foundational principles behind
django-tenant-users.
Happy coding!