Setting LOGIN_URL dynamically, for different users, based on app?

1,570 views
Skip to first unread message

dpapathanasiou

unread,
Jul 21, 2011, 9:15:17 PM7/21/11
to Django users
I'd like to be able to support two different types of authenticated
users within a single django project site.

The idea is that Type A users will work in the /dashboard app, and
Type B users will work in the /console app.

Since each app has its own set of models and views, I can do this at
the db level (i.e., /dashboard users have one set of tables, and /
console users have another).

But if I use the built-in django authentication api (https://
docs.djangoproject.com/en/dev/topics/auth/), it seems that I can only
define one value of LOGIN_URL in the project settings.py file.

Is there a way to set LOGIN_URL so that the /dashboard views.py
functions redirect to one location, while the views.py functions for /
console use a different value?

Andre Terra

unread,
Jul 21, 2011, 9:23:00 PM7/21/11
to django...@googlegroups.com
Why not make custom user profiles and write permission checks on your views?

Cheers,
AT


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.


dpapathanasiou

unread,
Jul 21, 2011, 10:15:02 PM7/21/11
to Django users
How can I do that in the context of the built-in django auth API? Are
there examples or tutorials of that?

Shawn Milochik

unread,
Jul 21, 2011, 10:17:09 PM7/21/11
to django...@googlegroups.com
On 07/21/2011 10:15 PM, dpapathanasiou wrote:
> How can I do that in the context of the built-in django auth API? Are
> there examples or tutorials of that?

https://docs.djangoproject.com/en/1.3/topics/auth/#storing-additional-information-about-users

dpapathanasiou

unread,
Jul 22, 2011, 9:35:41 AM7/22/11
to Django users
Thanks for your reply, but now that I've read up on custom profile and
permissions, it doesn't seem like a solution.

Here's another way of explaining it: in my urls.py file, I have two
entries inside the urlpatterns definition, like this:

(r'^dashboard/', include('mysite.console.urls')),
(r'^console/', include('mysite.console.urls')),

And then inside the /dashboard/urls.py file I have this:

urlpatterns = patterns('',
(r'^login/$',
'django.contrib.auth.views.login',
{'template_name': 'dashboard/login.html'}),

[etc]
)

And inside /console/urls.py is this:

urlpatterns = patterns('',
(r'^login/$',
'django.contrib.auth.views.login',
{'template_name': 'console/login.html'}),

[etc]
)

Basically, since /console and /dashboard provide different
functionality to different types of users, they have different
templates (and their db model definitions are quite different; /
dashboard users are not a type of /console user, nor can they really
be both inherited from the same user profile class).

So, ideally, what I'd like to be able to do is something like this, to
force the built-in authentication to use a different url than the
single LOGIN_URL specified in settings.py:

urlpatterns = patterns('',
(r'^login/$',
'django.contrib.auth.views.login',
{'template_name': 'dashboard/login.html', LOGIN_URL='/dashboard/
accounts/'}),

[etc]
}

and:

urlpatterns = patterns('',
(r'^login/$',
'django.contrib.auth.views.login',
{'template_name': 'console/login.html', LOGIN_URL='/console/
profile/'}),

[etc]
}

Is there a way to do that?

On Jul 21, 9:23 pm, Andre Terra <andrete...@gmail.com> wrote:

Andre Terra

unread,
Jul 22, 2011, 9:54:16 AM7/22/11
to django...@googlegroups.com
No, there is no way to do that. I'm sorry, but your approach is convoluted and inherently wrong.

Instead of asking "how can I make this solution work?" you should be asking "what's the best way to solve my needs?" and the answer to the latter will be very different from what you currently have in mind.

IDEAS:

* There is no reason you will need two login pages. Ideally, users should authenticate against the system as a whole, or you will rewrite the same logic in many places and the code will be huge and hard to maintain.
* Navigating through the site (and therefore accessing objects) is the part that needs the permission checks.
* Working with different models doesn't mean users have to live in two separate system. Again, think about permissions. Don't worry about the models until you get the profile permissions figured out.
* What if an admin needs to work on both the dashboard and the console? Where would he login?
* Apps should be as pluggable as possible. In that sense, have each app define its own urls and let the project-wide urls handle login.
* If you really need to (and I don't see why you would), write custom auth backends if you want, and restrict a user's login based on his profile's access level.


Regards,
AT


dpapathanasiou

unread,
Jul 22, 2011, 10:08:19 AM7/22/11
to Django users
Without getting into what's "right" or "wrong", I can explain that the
two types of users are inherently different, i.e., not inheritable
from a common base class, so user profiles and permissions will not
work, because functions in /dashboard views.py should never be
accessed (or in a position to be accessed) by functions in /console
views.py and vice versa.

Other than user models they do share data in common, which is why they
all need to run on one site.

As for your points about site admin, I do not want two login systems;
I simply want the core login system to redirect to different paths
when it's dealing with one app's user versus another.

I did think about your last point, i.e., writing a custom login/
authentication routine for one app, but that defeats the purpose of
using a framework in the first place.

Phang Mulianto

unread,
Jul 22, 2011, 10:16:19 AM7/22/11
to django...@googlegroups.com

with user profile, i translate it this way :
after user login,app check the profile of user then decide based on the profile which page sould user be redirected after login,say a to dashboard landing page, b user redirect to console page...

why would create 2 login page for 1 project anyway..

Andre Terra

unread,
Jul 22, 2011, 10:25:43 AM7/22/11
to django...@googlegroups.com
On Fri, Jul 22, 2011 at 11:08 AM, dpapathanasiou <denis.pap...@gmail.com> wrote:
Without getting into what's "right" or "wrong", I can explain that the
two types of users are inherently different, i.e., not inheritable
from a common base class, so user profiles and permissions will not
work, because functions in /dashboard views.py should never be
accessed (or in a position to be accessed) by functions in /console
views.py and vice versa.

This still doesn't explain what's preventing you from writing a check on each view. With the recent addition of Class-based Views to core, this would be as easy as writing two different Mixins, one in each views.py and have each function in the module subclass it. 
 
(...)


As for your points about site admin, I do not want two login systems;
I simply want the core login system to redirect to different paths
when it's dealing with one app's user versus another.

Redirecting User A to Path A won't prevent him from manually typing an the url to Path B and accessing the models. 
 
I did think about your last point, i.e., writing a custom login/
authentication routine for one app, but that defeats the purpose of
using a framework in the first place.

The good think about frameworks is that the heavy lifting has already been done for you.

https://docs.djangoproject.com/en/dev/topics/auth/#writing-an-authentication-backend



Cheers,
AT


 

dpapathanasiou

unread,
Jul 22, 2011, 10:32:14 AM7/22/11
to Django users
Ah, ok, that makes sense -- I'm not sure if that's what Andre meant in
the first place.

So you're saying: have the function which handles the post-login
request (i.e., defined in with LOGIN_REDIRECT_URL in settings.py and
in urls.py to some corresponding views.py function) make that type
check of user A/B, and simply redirect accordingly?

Alexey Luchko

unread,
Jul 22, 2011, 11:06:16 AM7/22/11
to django...@googlegroups.com
On 22.07.2011 17:32, dpapathanasiou wrote:
> So you're saying: have the function which handles the post-login
> request (i.e., defined in with LOGIN_REDIRECT_URL in settings.py and
> in urls.py to some corresponding views.py function) make that type
> check of user A/B, and simply redirect accordingly?

You can try redirect twice. Set fixed LOGIN_REDIRECT_URL to a view that
makes further redirect based on user permissions.

Or you can try fixed hidden input next in the login templates.

--
Regards,
Alexey.

dpapathanasiou

unread,
Jul 23, 2011, 11:13:10 AM7/23/11
to Django users
That's interesting, I hadn't thought about using a hidden input for
next in the two login templates.

In the end, though, I went with just one login template.

And rather than use UserProfiles (since there were no additional
attributes I needed to attach to the default User model, and my two
user types were not related otherwise), I with Groups (https://
docs.djangoproject.com/en/dev/topics/auth/#groups) instead.

I.e., I created two groups, one for each type of user, and at signup,
assigned them to group A/B accordingly.

LOGIN_REDIRECT_URL was set to a view function that checked the Group
belonging to request.user, and dispatched to the right start page.

I also wrote a decorator for each view function in /dashboard and /
console, to check that the given request.user was eligible to invoke
the underlying function.

So far, in test, it does exactly what I need it to do, based on the
original design.

So, I'd like to say thank you to everyone who replied to this thread;
your suggestions were helpful, and I wouldn't have discovered the
Groups capability without them.

Alexey Luchko

unread,
Jul 25, 2011, 12:23:22 PM7/25/11
to django...@googlegroups.com
On 23.07.2011 18:13, dpapathanasiou wrote:
> That's interesting, I hadn't thought about using a hidden input for
> next in the two login templates.
>
> In the end, though, I went with just one login template.
>
> And rather than use UserProfiles (since there were no additional
> attributes I needed to attach to the default User model, and my two
> user types were not related otherwise), I with Groups (https://
> docs.djangoproject.com/en/dev/topics/auth/#groups) instead.
>
> I.e., I created two groups, one for each type of user, and at signup,
> assigned them to group A/B accordingly.
>
> LOGIN_REDIRECT_URL was set to a view function that checked the Group
> belonging to request.user, and dispatched to the right start page.
>
> I also wrote a decorator for each view function in /dashboard and /
> console, to check that the given request.user was eligible to invoke
> the underlying function.
>
> So far, in test, it does exactly what I need it to do, based on the
> original design.
>
> So, I'd like to say thank you to everyone who replied to this thread;
> your suggestions were helpful, and I wouldn't have discovered the
> Groups capability without them.


I've got a question on the solution. Does it allow access to the other app
by direct url after successful login and redirect?


--
Regards,
Alexey.

dpapathanasiou

unread,
Jul 25, 2011, 6:18:22 PM7/25/11
to Django users


On Jul 25, 12:23 pm, Alexey Luchko <l...@ank-sia.com> wrote:
> On 23.07.2011 18:13,dpapathanasiouwrote:
> I've got a question on the solution.  Does it allow access to the other app
> by direct url after successful login and redirect?

No, because the decorator function checks the Group of request.user
and rejects the request if it's the wrong Group for this app.

Each app has its own signup function, and every new user gets exactly
one Group assignment, based on from which he registered.

One possible hole, though, is through the admin site: if a rogue
administrator assigns a user both Groups, then that user would gain
access exactly as you describe.
Reply all
Reply to author
Forward
0 new messages