django-tenant-schemas:如何使用单租户/没有子域

时间:2015-02-23 05:00:35

标签: python django postgresql

我开始在我的项目中使用django-tenant-schemas,所有数据表(用户等)完全分开。

我的要求是,我可以将私有服务器中的相同代码库部署到单个客户,也可以部署在多个云上。 django-tenant-schemas的路由不支持。如果我只有一个租户,它仍然需要一个子域来进行数据库路由。

对于使用runserver进行localhost开发我现在需要在/ etc / hosts中添加一行以使其正常工作,如:

127.0.0.1       testtenant.localhost.com

我怎样才能解决这个问题?

1 个答案:

答案 0 :(得分:5)

此自定义中间件扩展了django-tenant-schemas中的原始中间件,检查是否只存在一个租户模式,并设置与它的请求数据库连接。有了它,你可以简单地创建一个租户并继续使用例如localhost:8000用于开发工作以及为单个租户托管。

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)

设置自定义中间件而不是原始中间件:

MIDDLEWARE_CLASSES = ( 
    'middleware.apps.schemas.router.SchemaRouterMiddleware',
     ...
)