Tim-Tam
Tim-Tam

Reputation: 11

Django Tenants does not switch between tenants

I'm using django-tenants lab for developing my project. For each registered user, a tenant is created. Access to the tenant has to be via sub-folder project-url.ru/user/<username>/... instead of sub-domain <username>.project-url.ru/...

However, when entering a tenant app, Django does not change the tenant/scheme to the user one, and remains in public.

Please help me figure out why Django does not switch between tenants/schemes.

setting.py

SHARED_APPS = [
    'django_tenants',
    'users',
    ...,
]

TENANT_APPS = [
    'products',
    ...
]

INSTALLED_APPS = SHARED_APPS + [app for app in TENANT_APPS if app not in SHARED_APPS]


TENANT_MODEL = 'users.Tenant'
TENANT_DOMAIN_MODEL = 'users.Domain'
PUBLIC_SCHEMA_URLCONF = 'users.users-urls'
TENANT_SUBFOLDER_PREFIX = '/user'

DATABASE_ROUTERS = (
    'django_tenants.routers.TenantSyncRouter',
)

MIDDLEWARE = [
    'django_tenants.middleware.TenantSubfolderMiddleware',
    ...
]

Creating new tenant

def create_user_tenant(request):
    
    user = UserClass.objects.get(username=request.POST['username'])
    schema_name = f'{user.username}_schema'

    try:
        with transaction.atomic():
            tenant = Tenant(schema_name=schema_name, user=user)
            tenant.save()
            logger.debug(f'Tenant {tenant} created')
    except IntegrityError as e:
        logger.error(f'Error creating tenant or domain for user {user.username}: {e}')
    except Exception as e:
        logger.error(f'Unexpected error creating tenant or domain for user {user.username}: {e}')

New schema created in DB. I checked. Here is urls settings:

users-url.py

urlpatterns = [
    path('<str:username>/products/', include('products.products-urls', namespace='products')),
    path('<str:username>/storage/', include('storage.storage-urls', namespace='storage')),
    ...

]

products-urls.py

urlpatterns = [
    ...

    path('items-list/', items_list, name='items-list'),
    ...
]

Authorization:

def login(request):

    error_msg = ''

    if request.POST:
        logger.debug(f"Login request")
        form = UserLoginForm(data=request.POST)
        if form.is_valid():
            username = request.POST['username']
            password = request.POST['password']
            user = auth.authenticate(username=username, password=password)
            if user:
                logger.debug(f"User {username} authenticated")
                auth.login(request, user)
                return redirect(f'/{username}/products/items-list/')

After successful authorization should run this

@transaction.atomic
def items_list(request, username):
    logger.debug(f'Current connected schema: {connection.schema_name}')

    context = {
        'username': UserClass.objects.get(username=username),
        'items_list': ItemsClass.objects.order_by('name'),
    }

    return render(request, 'products/items/items_list.html', context)

But on the page I caught the error that some fields can not be found in DB, because they are only in tenant app.

ProgrammingError at /aaa/products/items-list/
relation "products_itemsclass" does not exist
LINE 1: ...fats", "products_itemsclass"."carbohydrates" FROM "products_...

In the log

2024-08-19 12:18:23,979 - DEBUG (item_view.items_list): Current connected schema: public

And should be <username>_schema. Please help to figer out why is that...

I follow the documentation: https://django-tenants.readthedocs.io/en/latest/install.html#sub-folder-support

Upvotes: 0

Views: 43

Answers (0)

Related Questions