Reputation: 11
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