would is_loggedin be better than is_anonymous?

35 views
Skip to first unread message

Gary Wilson

unread,
Jul 10, 2006, 11:05:46 PM7/10/06
to Django developers
Proposing an is_loggedin method for User and AnonymousUser models.

Templates treat non-existing variables as False; therefore; a
request.user somehow failing to get assigned would result in the
template treating the user as they are authenticated (is_anonymous
evaluates False). An is_loggedin would be a more secure option because
if request.user failed to get assigned, the template would treat the
user as anonymous.

I would much rather mistakenly treat an authenticated user as anonymous
than mistakenly treat an anonymous user as authenticated.

is_anonymous could be changed to return the negation of is_loggedin.

Thoughts?

Malcolm Tredinnick

unread,
Jul 10, 2006, 11:31:47 PM7/10/06
to django-d...@googlegroups.com

I like this. :-)

I would prefer to declare is_anonymous as deprecated, though, rather
than just make it work transparently again. Then we can consider
removing it in some weeks/months (prior to 1.0). It will always be
dangerous if your above logic is correct -- just tying it to
is_logged_in (is_authenticated?) does not change that -- so we should
force people to use the right method.

Malcolm

SmileyChris

unread,
Jul 11, 2006, 11:34:43 PM7/11/06
to Django developers
I like it too.

To attone for my duplicate thread, I have created a ticket and patch
for this.
http://code.djangoproject.com/ticket/2332

I'm not sure how you "declare is_anonymous as depreciated", Malcom so
I'll leave that to you ;)

Gary Wilson

unread,
Jul 12, 2006, 12:34:24 AM7/12/06
to Django developers
Thinking of this some more, I'm wondering about the names is_logged_in
or is_authenticated. They could be a little misleading since they
aren't really checking if the user is logged in or not. One might be
led to believe that they could do something like logged_in_users =
[user.is_logged_in() for user in User.objects.all()] or something like
user = User.objects.get(username='fred'); if user.is_logged_in(): ...

It seems that maybe the is_anonymous function is just a way for the
object to say it's either an AnonymousUser object or it's not an
AnonymousUser object.

Malcolm Tredinnick

unread,
Jul 12, 2006, 1:17:46 AM7/12/06
to django-d...@googlegroups.com

Hmm ... good points. We document is_anonymous() the way you describe it
in the last paragraph. In the same document, we use it in the slightly
accident-prone fashion your original post (and the thread on
django-users) described.

Considering alternatives in order of decreasing "stuipdness": one fix is
to make improvement in the documentation: "If you are going to put a
"members only" block of text up, you should check that user.id evaluates
as True." It is guaranteed that id == None on AnonymousUser objects.

Another possibility is to call the name "not_anonymous" (but not really
that name, since it's a pretty stupid name). Does "registered" work as a
name?

I guess I prefer finding a better name, rather than hoping for "success
through documentation".

Malcolm

SmileyChris

unread,
Jul 12, 2006, 6:16:20 PM7/12/06
to Django developers
Yea, I'm not really that sold on .is_loggedin() either... some
alternatives:

.is_real_user()
.is_known()

Gary Wilson

unread,
Jul 13, 2006, 1:24:30 AM7/13/06
to Django developers
What if we instead make it so that context_processor.auth only sets the
"user" template variable if request.user is not an AnonymousUser
instance and then in templates you would use

{% if user %}
I am logged in.
{% endif %}

to determine if the user is logged in. If the user is not logged in,
then the "user" template variable will not get set and then the above
would evaluate to False.

I also got to thinking about the AuthenticationMiddleware setting
request.user to None instead of an AnonymousUser object (and doing away
with the AnonymousUser class) when the user is not logged in; however,
in views and code it is probably nice to be able to things like
request.user.has_perm('myperm') without having to put an "if user:"
check before it all the time.

But in the templates, this is not the case because you can do {% if
user.has_perm('myperm') %} without doing an {% if user %} check since
the "user" template variable wouldn't exist and would evaluate to False.

SmileyChris

unread,
Jul 13, 2006, 5:36:11 PM7/13/06
to Django developers
I think we still need the AnonymousUser and from the number of
references to is_anonymous in python modules I think we still need a
negation of it.

So how can we work towards a consensus on the best name for a function
which is the negative of is_anonymous?

On a side note, in templates I don't think you can actually do {% if
user.has_perm('myperm') %} anyway.

Gary Wilson

unread,
Jul 13, 2006, 6:07:07 PM7/13/06
to Django developers
SmileyChris wrote:
> I think we still need the AnonymousUser and from the number of
> references to is_anonymous in python modules I think we still need a
> negation of it.

Yes I think AnonymousUser is still helpful in python code, and yes I
think we should deprecate is_anonymous before removing it.

> So how can we work towards a consensus on the best name for a function
> which is the negative of is_anonymous?

I think I now vote for is_authenticated since the is_loggedin versions
could more easily be taken the wrong way (by trying to lookup all users
who are logged in). I would be less inclined to try and lookup all
users who are authenticated. Make any sense?

> On a side note, in templates I don't think you can actually do {% if
> user.has_perm('myperm') %} anyway.

Yes, I must have been brain dead. But it would still hold true that
the "user" template variable could just not be set instead of setting
it to an AnonymousUser instance. Hmm, this would break pretty badly
for people using {% if not user.is_anonymous %} in their templates
though since it would then treat all non-authenticated users as
authenticated. So scratch this idea.

Jacob Kaplan-Moss

unread,
Jul 13, 2006, 6:12:43 PM7/13/06
to django-d...@googlegroups.com
On Jul 13, 2006, at 4:36 PM, SmileyChris wrote:
> On a side note, in templates I don't think you can actually do {% if
> user.has_perm('myperm') %} anyway.

You actually can (if you're using RequestContext)::

{% if perms.auth.can_add_user %}
...
{% endif %}

Jacob

SmileyChris

unread,
Jul 13, 2006, 7:49:52 PM7/13/06
to Django developers
Gary Wilson wrote:
> I think I now vote for is_authenticated since the is_loggedin versions
> could more easily be taken the wrong way (by trying to lookup all users
> who are logged in). I would be less inclined to try and lookup all
> users who are authenticated. Make any sense?

Makes sense to me. And I agree that is_loggedin is definately the wrong
name.
Unless someone else suggests something better, my vote is for
is_authenticated too.

I was also keen on Malcom's idea of just using user.id but on further
thought it seems a bit implicit. Explicit is good, right?

Gary Wilson

unread,
Jul 14, 2006, 10:50:52 AM7/14/06
to Django developers
And so are we keeping is_anonymous or deprecating it? I guess it would
still be useful for determining whether on not your object is an
AnonymousUser instance, which seems to be it's original intent. We can
keep it and just change the docs to use is_authenticated.

Adrian Holovaty

unread,
Jul 14, 2006, 11:33:58 AM7/14/06
to django-d...@googlegroups.com

Yeah, I tend to agree with this solution (changing the docs to use
is_authenticated or whatever the name of the new method is).

Adrian

--
Adrian Holovaty
holovaty.com | djangoproject.com

Jacob Kaplan-Moss

unread,
Jul 14, 2006, 12:04:25 PM7/14/06
to django-d...@googlegroups.com
On Jul 14, 2006, at 10:33 AM, Adrian Holovaty wrote:
> On 7/14/06, Gary Wilson <gary....@gmail.com> wrote:
>> And so are we keeping is_anonymous or deprecating it? I guess it
>> would
>> still be useful for determining whether on not your object is an
>> AnonymousUser instance, which seems to be it's original intent.
>> We can
>> keep it and just change the docs to use is_authenticated.
>
> Yeah, I tend to agree with this solution (changing the docs to use
> is_authenticated or whatever the name of the new method is).

I agree -- keep is_anonymous but emphasize is_authenticated in the docs.

Jacob

SmileyChris

unread,
Jul 14, 2006, 5:53:47 PM7/14/06
to Django developers
Hrm...
Will there ever be a difference between "user.is_anonymous" and "not
user.is_authenticated"?
If not (and I can't think of a reason), do we really need to keep
is_anonymous?

Mikeal Rogers

unread,
Jul 14, 2006, 6:04:10 PM7/14/06
to django-d...@googlegroups.com
I can see a use case where you use 'anonymous' as a kind of temporary account for users who access the site in some way other than the usual means.

For example if a user gets an invitation to something, like an evite or calendar, an url could be generated that auto-authenticated them into the 'anonymous' account, which would mean they were authenticated but limited to a temporary anonymous account and would only have limited use.

-Mikeal

SmileyChris

unread,
Jul 14, 2006, 6:18:20 PM7/14/06
to Django developers
As long as you're using RequestContext however, the user would always
either be an anonymous user or an authenticated user.
But I guess you don't have to use RequestContext, therefore I'm
answering my own question...

So Adrian (or other submitters), do you need any more work done to
Gary's patch or can you work it from there? I guess if someone who's
good with their English wants to provide a patch for the documentation
then that would be a help.

Gary Wilson

unread,
Jul 17, 2006, 9:12:17 PM7/17/06
to Django developers
Patch for is_authenticated implementation with doc changes and no
deprecation warnings in is_anonymous. Please review.

http://code.djangoproject.com/attachment/ticket/2332/is_authenticated.2.diff

Malcolm Tredinnick

unread,
Jul 17, 2006, 9:43:32 PM7/17/06
to django-d...@googlegroups.com
Hi Gary,

I'm going to sit down this evening and close some tickets. If nobody
gets to this before then, I'll deal with it then.

Cheers,
Malcolm

Joost Cassee

unread,
Jul 16, 2008, 9:48:10 AM7/16/08
to SmileyChris, django-d...@googlegroups.com

I would like to present a case for such a difference. Look at
Amazon.com. They seem to have three user authentication levels: 1)
anonymous users, 2) identified users and 3) authenticated users. I
have been trying to implement a feature like that for Django as an
application, but it dives so deep into the authentication process that
I am probably going to submit a patch.

Of course, said app (or patch) does not yet exist, but I feel the
potential need for distinguishing anonymous from authenticated users
is there.


Regards,

Joost

Nathan Hoover

unread,
Jul 16, 2008, 9:51:34 AM7/16/08
to django-d...@googlegroups.com
I'll second that. I work for a large (unfortunately non-django) commercial web property and we have the same basic set of states - anonymous, known, and authenticated. I think it's pretty common.

Regards,
Nathan

Robert Coup

unread,
Jul 16, 2008, 8:05:04 PM7/16/08
to django-d...@googlegroups.com
On Thu, Jul 17, 2008 at 1:51 AM, Nathan Hoover <nat...@foo-o-rama.com> wrote:
I'll second that. I work for a large (unfortunately non-django) commercial web property and we have the same basic set of states - anonymous, known, and authenticated. I think it's pretty common.

Its not that hard to handle...

1. Have long-lived sessions:
 - if there isn't a user associated: "anonymous"
 - if it has a user: "known"

2. When a user logs in (ie. types their username and password):
 - add the user reference to the session (this is done by Django's default login view)
 - create a separate token (time+random+userid+secret, etc) and:
    - add it to the session
    - send it in a separate cookie (eg. auth_token) to the browser. Have this cookie being short-lived (browser session or short expiry time)

3. When you want to check for authenticated:
 - check the session has a user
 - check the auth_token cookie exists in the request
 - check the auth_token cookie value matches the corresponding value stored in the session
if all match, the user is "authenticated". Otherwise they're "known", but need re-authenticating (ie. please confirm your password to continue), in which case the new auth_token is created as in (2).

Doing all the above overrides the login view - which is common to override anyway afaik, and maybe adds a view decorator to check for "authenticated" (eg. @authenticated_login_required)

HTH, maybe i should blog it or add to django-snippets.

Rob :)

Joost Cassee

unread,
Jul 17, 2008, 5:18:35 AM7/17/08
to Django developers
On 17 jul, 02:05, "Robert Coup" <robert.c...@onetrackmind.co.nz>
wrote:

> Its not that hard to handle...
>
> 1. Have long-lived sessions:
>  - if there isn't a user associated: "anonymous"
>  - if it has a user: "known"
>
> 2. When a user logs in (ie. types their username and password):
>  - add the user reference to the session (this is done by Django's default
> login view)
>  - create a separate token (time+random+userid+secret, etc) and:
>     - add it to the session
>     - send it in a separate cookie (eg. auth_token) to the browser. Have
> this cookie being short-lived (browser session or short expiry time)

I had done it just the other way around: use session cookies and add a
long-lived cookie for identification. :-)

> 3. When you want to check for authenticated:
>  - check the session has a user
>  - check the auth_token cookie exists in the request
>  - check the auth_token cookie value matches the corresponding value stored
> in the session
> if all match, the user is "authenticated". Otherwise they're "known", but
> need re-authenticating (ie. please confirm your password to continue), in
> which case the new auth_token is created as in (2).
>
> Doing all the above overrides the login view - which is common to override
> anyway afaik, and maybe adds a view decorator to check for "authenticated"
> (eg. @authenticated_login_required)

If you override the login view you will not catch calls to login /
authenticate from Python, but maybe that is not so important. (I was
looking for a general solution.) Additionally, existing code like the
admin interface should still only work for authenticated users, so you
can not get away with adding a new decorator for 'really authenticated
users'. My solution had the User object wrapped in a proxy that
returns False on is_anonymous() and is_authenticated().


Regards,

Joost
Reply all
Reply to author
Forward
0 new messages