How to make Django test client send requests to different subdomains - python

I am using the django-subdomains project to enable subdomains in my django project, which works fine.
However, when writing tests, I cannot figure out how to make the Django test client send requests to different subdomains.
It only sends requests to the root domain even if I change the ROOT_URLCONF to point to one of the entries in SUBDOMAIN_URLCONFS with #override_settings. But it works if I directly change the ROOT_URLCONF in settings.py to the desired subdomain urlconf, which is obviously an unacceptable solution.
Also tried to subclass the Django TestCase class and set the "url" field to the subdomain urlconf but the request is still going to root, resulting in 404.
Finally, I tried to use subdomains.utils.reverse to get an absolute url, but the test client does not accept this at all.
This question may be related to Django Test Client and Subdomains. Someone mentioned in a comment that a hack has been used to solve this. Please elucidate said hack or even better, a proper solution to address this surely not-so uncommon use case.

HTTP_HOST = 'rede.example.com'
class TestIndexView(TestCase):
def setUp(self):
self.url = subdomain_reverse('network_index', subdomain='rede')
def test_render(self):
response = self.client.get(self.url, HTTP_HOST=HTTP_HOST)
self.assertEqual(response.status_code, 200)

Related

Django: setting a different SESSION_COOKIE_DOMAIN depending on the domain

I use the same Django project for various domains. Some are subdomains, some are entirely different domains, so I have these domains operating the same Django site:
a.example1.com
b.example1.com
c.example1.com
example1.com
example2.com
I do not use the sites framework for reasons unrelated to this query, and I have a single settings.py for all sites, which I'd like to maintain.
When someone logs onto a subdomain, I'd like them to be logged onto any of the other subdomains as well. In fact, if it were possible I'd like them to be logged onto the other sites as well but I doubt this is possible. In order to achieve logging into all subdomains at the same time, I set the following variable in settings.py:
SESSION_COOKIE_DOMAIN=".example1.com"
This works as advertised and the logins are now working across different sites. However, I am not able to log onto any of the other domains anymore (I assume the cookie is set for the wrong domain and subsequently not properly recognized). What I assume I should do is somehow set SESSION_COOKIE_DOMAIN to either .example1.com when on the main site, or .example2.com when I'm on a different site. But how to achieve this?
Here is a similar question and this answer seems to do what I am looking for through a lightweight solution. However, this is written for older Django versions. I tried rewriting this for Django 3 as follows:
class CrossDomainSessionMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
try:
if request.COOKIES:
host = request.get_host()
# check if it's a different domain
if host not in settings.SESSION_COOKIE_DOMAIN:
domain = ".{domain}".format(domain=host)
for cookie in request.COOKIES:
if "domain" in request.COOKIES[cookie]:
request.cookies[cookie]['domain'] = domain
except:
pass
return self.get_response(request)
But this doesn't seem to work. This condition:
if "domain" in request.COOKIES[cookie]:
Is simply never met. Not sure what I should change.

Can I tell where my django app is mounted in the url hierarchy?

I need to redirect my clients to another endpoint in my django app. I know I can use relative urls with request.build_absolute_uri() to do this, but I am searching for a generic solution that doesn't require the redirecting handler to know its own place in the URL hierarchy.
As an example, I have handlers at the following two URLs:
https://example.com/some/other/namespace/MY_APP/endpoint_one
https://example.com/some/other/namespace/MY_APP/foo/bar/endpoint_two
Both handlers need to redirect to this URL:
https://example.com/some/other/namespace/MY_APP/baz/destination_endpoint
I would like for endpoint_one and endpoint_two to both be able to use the exact same logic to redirect to destination_endpoint.
My app has no knowledge of the /some/other/namespaces/ part of the URL, and that part of the URL can change depending on the deployment (or might not be there at all in a development environment).
I know I could use different relative urls from each endpoint, and redirect to the destination URL. However, that required that the handlers for endpoint_one and endpoint_two know their relative position in the URL hierarchy, which is something I am trying to avoid.
After doing more research and talking with coworkers, I realized that reverse does exactly what I need.

how to disable caching of filter results in jinja2

We are working on a Pyramid (with Jinja2 templates through pyramid_jinja2) application that gives user his unique subdomain and a way to change this subdomain to any other available subdomain later.
So, for example, you can go to sub.example.com/settings and change your subdomain to "dub". After submitting this change you are redirected to dub.example.com/settings.
We have one issue with this setup - because our subdomain is stored in request object and we have custom pregenerators for every subdomain-based view - when we call route_url while we are on sub.example.com - the result seems to be cached and the same url is generated when we change our subdomain. So for example after the subdomain change (until we restart our application) we are on the site with dub.example.com address, but some links (menu, "action" targets in some forms) have still "sub.example.com" in the url, because this url was generated before subdomain change.
I have a problem finding on what level the generated url is cached and all in all - I have no good idea how to avoid it. Disabling cache of url generation is less then perfect (though I didn't even know it was "a thing" until now).
What is in your opinion best way of working out that kind of issue?
Took me some time to debug this issue, but created a patch for pyramid_jinja2. See https://github.com/Pylons/pyramid_jinja2/pull/74.
The filter is being evaluated as const, (function as_const in nodes.py of jinja2), causing the filter to only being executed once.

Authenticating user from SSO + OpenID in django for google apps custom domain

After a lot of reading and researching i found the following library, the most suited to work for my needs: to signup/login a user using a custom google apps domain.
I did the following settings:
GOOGLE_APPS_DOMAIN = 'example.com'
GOOGLE_APPS_CONSUMER_KEY = 'example.com'
GOOGLE_APPS_CONSUMER_SECRET = '*sekret*'
# domain where your application is running
GOOGLE_OPENID_REALM = 'http://*.hudora.biz/'
GOOGLE_OPENID_ENDPOINT = 'https://www.google.com/accounts/o8/ud'
added custom middlewares and other stuff.
But from now, where do i take it further, showing a form and making form posts to urls, how do i ask user information, it is not given in the docs.
Can anybody please help me with it?
How do i give a user the functionality to login/signup?
How do i customize a view?
You are almost there. For the sake of testing it on your localhost following are things you need to do:
You need to register an app at the Google API Console (while registering, put your domain 127.0.0.1:8000 or the exact location where your server is running)
You need to check the scope for your project, eg. calendar or maps etc.
You need to get the secret key.
Once you have got the secret, put them in your settings file, as described above. Change example.com and *.hudora.biz to 127.0.0.1:8000
Import the views from the library views for login and logout and map them to your urls probably login/logout.
This is all that is reqd. Hope it helps!

Django multitenant urls configuration

I am trying to add some simple tenancy support to an app, creating an Account model which has a string 'tenant' to be read from the request url and identify the tenant in the system:
tenant.example.com/* -> www.example.com/tenant/* (rewritten by apache)
I wrote a simple middleware to capture this /tenant/ from request.path and add a request.account object to be worked with.
My problem is my url mapping.
I tried this:
url(r'^(?P<tenant_id>[\w\-]+)/', include('project.urls_tenant')),
and defined some simple urls inside urls_tenant.py:
url(r'^app1/', include('project.app1.urls')),
url(r'^app2/', include('project.app2.urls')),
When I try to access any page, I get an error message:
generic_view_method() got an unexpected keyword argument 'tenant_id'
because it doesn't (and really shouldn't) expect tenant_id as a parameter.
If I hardcode tenant_id in the urls.py file as /test_tenant/ everything works fine.
What am I doing wrong and how to fix it, so the request and the response gets processed normally?
Thank you guys pretty much. I used this as reference: optimal architecture for multitenant application on django
You are capturing the named parameter tenant_id in the url pattern when you apparently don't need to. Try removing the parentheses to avoid performing the capture:
url(r'^[\w\-]+/', include('project.urls_tenant')),
This page is a generally useful read:
https://docs.djangoproject.com/en/dev/topics/http/urls/#how-django-processes-a-request
If I understand your setup correctly you have defined:
url(r'^(?P<tenant_id>[\w\-]+)/', include('project.urls_tenant')),
In our main urls.py file and the other lines in your urls_tenant.py file ?
Taking it from there wouldn't any request that matches ^(?P[\w-]+)/ be passed
through urls_tenant.py file ? The two lines you have defined there would only be able to match /app1 or /app2.
But I'm just guessing I'm not fully understanding your setup ?
I think it would be better if you would map the tenant url to a specific view instead of including a different urls.py file
(I didn't even know this was possible).
url(r'^(?P<tenant_id>[\w\-]+)/', TenantView.as_view(), name="tenant-view"),
Something like the above looks more django to me.

Categories