Open killer24vrccp opened 2 months ago
The django-tenants
middleware is responsible for adding the tenant
key on the request
object.
There are reasons it won't do that (see the try/except earlier in the method), so I would suggest adding a debug point in the process_request()
and see why that key isn't being set.
Hey @killer24vrccp, the error is caused by the ordering in the middleware (weird, I know :P). Just ensure the tenant_user middleware comes after the django auth middleware like so:
"django.contrib.auth.middleware.AuthenticationMiddleware",
"tenant_users.tenants.middleware.TenantAccessMiddleware",
Good catch @thubamamba! Yes, the tenant_users middleware requires the AuthenticationMiddle since it's checking for authentication status.
We should probably document this in the docs and middleware docstring. I did originally write this as a starting point since a few people were asking, but by no means is it meant to fit every use case.
Hey @thubamamba I have try but I have the same error. I don't knwo why.
Environment:
Request Method: GET
Request URL: http://localhost:8000/en/
Django Version: 4.2.15
Python Version: 3.10.11
Installed Applications:
['jazzmin',
'django_tenants',
'tenant_users.permissions',
'tenant_users.tenants',
'app.generic.business',
'app.generic.account',
'django.contrib.contenttypes',
'django.contrib.auth',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.humanize',
'django.contrib.admin',
'django.contrib.staticfiles',
'django.contrib.admindocs',
'django.contrib.sitemaps',
'rosetta',
'django_user_agents',
'rest_framework',
'rest_framework.authtoken',
'app.public.user_sessions',
'app.public.core',
'app.public.changelog',
'app.generic.address',
'app.generic.module',
'bootstrap5',
'app.api',
'django_htmx',
'crispy_forms',
'crispy_bootstrap5',
'django_countries',
'parler']
Installed Middleware:
['django_tenants.middleware.main.TenantMainMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'tenant_users.tenants.middleware.TenantAccessMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django_user_agents.middleware.UserAgentMiddleware']
Traceback (most recent call last):
File "D:\Projet\CVS_tenant\.venv\lib\site-packages\django\core\handlers\exception.py", line 55, in inner
response = get_response(request)
File "D:\Projet\CVS_tenant\.venv\lib\site-packages\tenant_users\tenants\middleware.py", line 44, in __call__
if not self.has_tenant_access(request):
File "D:\Projet\CVS_tenant\.venv\lib\site-packages\tenant_users\tenants\middleware.py", line 61, in has_tenant_access
return request.user.tenants.filter(id=request.tenant.id).exists()
Exception Type: AttributeError at /en/
Exception Value: 'WSGIRequest' object has no attribute 'tenant'
Exception Value: 'WSGIRequest' object has no attribute 'tenant'
Did you check out my prior comment? That tenant
attribute is added to the request object by django-tenants
middleware.
I would bet something is not setup right with django-tenants
as this line will cause request.tenant
not to be created. For the hostname you're trying to navigate to, is the domain setup? Try this from the shell:
from django_tenants.utils import get_tenant_domain_model
hostname = "whatever-you're-using"
domain_model = get_tenant_domain_model()
domain_model.objects.select_related('tenant').get(domain=hostname)
If that doesn't come up with anything, you'll get the error you're seeing.
I don't know if that's can help me but I use this command for approvisionning public tenant : python .\manage.py create_public_tenant --domain_url public.localhost --owner_email admin@admin.com
I have setup few print : localhost
Debug:
localhost
Internal Server Error: /favicon.ico
Traceback (most recent call last):
File "D:\Projet\CVS_tenant\.venv\lib\site-packages\django\core\handlers\exception.py", line 55, in inner
response = get_response(request)
File "D:\Projet\CVS_tenant\.venv\lib\site-packages\tenant_users\tenants\middleware.py", line 44, in __call__
if not self.has_tenant_access(request):
File "D:\Projet\CVS_tenant\.venv\lib\site-packages\tenant_users\tenants\middleware.py", line 61, in has_tenant_access
return request.user.tenants.filter(id=request.tenant.id).exists()
AttributeError: 'WSGIRequest' object has no attribute 'tenant'
def process_request(self, request):
# Connection needs first to be at the public schema, as this is where
# the tenant metadata is stored.
connection.set_schema_to_public()
try:
hostname = self.hostname_from_request(request)
print(hostname)
except DisallowedHost:
from django.http import HttpResponseNotFound
return HttpResponseNotFound()
domain_model = get_tenant_domain_model()
try:
tenant = self.get_tenant(domain_model, hostname)
print(tenant)
except domain_model.DoesNotExist:
self.no_tenant_found(request, hostname)
return
tenant.domain_url = hostname
request.tenant = tenant
connection.set_tenant(request.tenant)
self.setup_url_routing(request)
I'm confused - did you not try the commands I suggested?
I don't know if that's can help me but I use this command for approvisionning public tenant :
python .\manage.py create_public_tenant --domain_url public.localhost --owner_email admin@admin.com
You're creating a "domain" with the value public.localhost
.
I have setup few print : localhost
Debug:
localhost
The domain you're accessing is localhost
. Run the commands in my prior comment, or even Domain.objects.all()
. If you're accessing localhost
but the domain is set to public.localhost
, then the django-tenants
middleware won't find a match and will not create request.tenant
, hence the failure.
I managed to get this working, the issue was indeed that there was no tenant being passed to the request. So, the first thing you have to ensure to do is create a public tenant.. check out the django-tenant docs or the django-tenant-users.
@Dresdn Yes I have try. I have retry with python manage.py create_public_tenant domain_url localhost owner_email admin@admin.com
And result of command:
>>> hostname = "localhost"
>>> domain_model = get_tenant_domain_model()
>>> domain_model.objects.select_related('tenant').get(domain=hostname)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "D:\Projet\CVS_tenant\.venv\lib\site-packages\django\db\models\query.py", line 637, in get
raise self.model.DoesNotExist(
app.generic.business.models.Domain.DoesNotExist: Domain matching query does not exist.
>>>
Let's ensure we're on the same page. Can you confirm the following?
You created the public tenant by using: python manage.py create_public_tenant --domain_url public.localhost --owner_email admin@admin.com
I see you re-tried it, but was that a clean database?
You're navigating to http://localhost:8000
? If not, what "hostname" are you browsing to?
Whatever that hostname is, is there a Domain
object created for it? Update the script you tried in the last comment.
To your last note, if there is no Domain
model, django-tenants
isn't setup correctly. You can check by seeing what domains are there via Domain.objects.all()
If you're trying to navigate to a URL that is not listed there, it will fail.
I would ensure you have everything setup as called out in the Installation Docs.
I have resolve the problem. I have juste use localhost then public.localhost. But raise a new problem. My tenant URL not work in my public tenant. Thats said NoReverseMatch 'interface' is not a registered namespace.
I use {% if request.tenant %}{% url 'interface.css-min %}{% endif %}
.
I have a problem with
TenantAccessMiddleware
. When user authentificated in public after in my public I receive this error: 'WSGIRequest' object has no attribute 'tenant'Account model
Tenant/Domain Model
When I'm on my tenant and I try to login i'm stay not authentificated. I have add this settings
SESSION_COOKIE_DOMAIN = ".localhost"
. I'm in localhost for dev.