I started using django-tenant-schemas for my project with all data tables (user, etc.) completely separated.
My requirements are that I can deploy the same code base in a private server to a single customer as well as on a cloud for multiple. The routing of django-tenant-schemas does not support that. If I only have a single tenant it will still require a subdomain for the database routing.
Also for localhost development with runserver I now need to add a line to my /etc/hosts to make it work, like:
127.0.0.1 testtenant.localhost.com
How can I get around that?
This custom middleware extends the original one of django-tenant-schemas, checks if only one tenant schemas exists and sets the request database connection to it. With that you can simply create a tenant and continue using e.g. localhost:8000 for you development work as well as hosting it for a single tenant.
from django.db import connection
from django.contrib.contenttypes.models import ContentType
from tenant_schemas.middleware import TenantMiddleware
from tenant_schemas.utils import get_tenant_model, get_public_schema_name
def get_tenant_schemas():
''' Return all tenant schemas '''
return get_tenant_model().objects.exclude(
schema_name=get_public_schema_name())
class SchemaRouterMiddleware(TenantMiddleware):
"""
Extends the original routing middleware from django-tenant-schemas.
To support both types of deployment (cloud with many tenants vs. single
tenant on own server) we check if our database holds more than one tenant:
- Yes: Select schema based on subdomain (= django-tenant-schemas default)
- No: Always use that single tenant's schema no matter what the
incoming host name is (ip, domain, subdomain, ...)
"""
single_tenant = False
def __init__(self):
'''
Adding a new tenant will most likely go with a server restart so we can
avoid querying the table with each request and only do this once here:
'''
tenants = get_tenant_schemas()
if tenants.count() == 1:
self.single_tenant = tenants[0]
def process_request(self, request):
if self.single_tenant:
connection.set_tenant(self.single_tenant)
request.tenant = self.single_tenant
ContentType.objects.clear_cache()
else:
super(SchemaRouterMiddleware, self).process_request(request)
Set the custom middleware instead of the original one:
MIDDLEWARE_CLASSES = (
'middleware.apps.schemas.router.SchemaRouterMiddleware',
...
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With