Opened 4 years ago

Closed 3 years ago

#17254 closed Bug (duplicate)

ModelBackend should have a get_anonymous_user method

Reported by: riccardodivirgilio Owned by: nobody
Component: contrib.auth Version:
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: yes Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

ModelBackend should provide a method to get a fresh instance of AnonymousUser, and use this method to set a new instance of AnonymousUser in

django.contrib.auth.get_user and django.contrib.auth.logout

Attachments (3)

backends.py (4.8 KB) - added by riccardodivirgilio 4 years ago.
backends.2.py (4.8 KB) - added by riccardodivirgilio 4 years ago.
rewrite the code with the var name "user_model" instead of "user_class"
backends.diff (1.4 KB) - added by riccardodivirgilio 4 years ago.

Download all attachments as: .zip

Change History (14)

comment:1 Changed 4 years ago by David Danier <david.danier@…>

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

Why do you want this? Guest accounts in the database?

comment:2 Changed 4 years ago by ptone

  • Resolution set to needsinfo
  • Status changed from new to closed

Please provide a use case, or argument about how the current implementation is problematic.

Are you attaching stuff to the user instead of just the session?

Changed 4 years ago by riccardodivirgilio

comment:3 Changed 4 years ago by anonymous

when you subclass the user, i would like to subclass even the AnonymousUser in request to check the user attributes without using getattr, or define custom methods, even for an AnonymousUser user.

for example, i have got a field that is called "user_discount" and i have got a method that return the final price of the user.

i use this method a lot of time in the site, because it's an commerce, and it's useful to do request.user.dicounted_price("120") without doing a mess like this get_discounted_price_from_user(user, 120), and using a function and not a class, and in every part of my code i have to check if user is_authenticated before using custom method of my user class.

for me an AnonymousUser, should be a subclass of the user class, but it must be declared importing the user class from the backend and then subclassing it.

i've a attached a new backend file,

this is an easy way to allow developers to completely use another User and Permission backend using 3 line of code (read the backends.py i've attached)

class MyModelBackend(ModelBackend):

user_class = MyUser
permission_class = MyPermission
anonymoususer_class = MyAnonymousUser

with this class i can set my own model table for existing legacy user and permission, without rewrite login, logout, password_change and so on...

comment:4 Changed 4 years ago by riccardodivirgilio

sorry for my english, i'm italian and i just woke up... yesterday i was drunk so sorry....

but read the backends.py for me it's much more customizable in the way i wrote...
the methods inside the backend use self.user_class.objects.get to get an user, instead of doing User.objects.get
i added a get_anonymous_user to get a fresh instance of AnonymousUser, this method must be used by the middleware
for me doing an import such "from django.contrib.auth.models import AnonymousUser" and then call directly AnonymousUser(), it'wrong, because if you do something like this, i have to rewrite more code to make login/logout and middleware work the way i need.

the way i wrote the backend, to subclass it you simply need to hook your user model and your anonimoususer class, and django will do the dirty of work of login, logout, password change and so on.

bye bye, my django friends!

Changed 4 years ago by riccardodivirgilio

rewrite the code with the var name "user_model" instead of "user_class"

comment:5 Changed 4 years ago by anonymous

with this implementation of backend i can do something like this
do not use "django.contrib.auth" in the INSTALLED_APP, but use "myapp.auth" to define User class and Permission class (with duck type mot hod of django class) and still use django.contrib.auth.urls and django.contrib.middleware.AuthenticationMiddleware, and everything works (with a different user and permission db_table)

comment:6 Changed 4 years ago by anonymous

  • Needs tests set

comment:7 Changed 4 years ago by ptone

  • Resolution needsinfo deleted
  • Status changed from closed to reopened

reopening to change resolution

comment:8 Changed 4 years ago by ptone

  • Resolution set to duplicate
  • Status changed from reopened to closed

This is basically a dupe of #3011

see also: http://stackoverflow.com/questions/896421/how-to-change-default-django-user-model-to-fit-my-needs

AnonUsers and AuthUsers are fundamentally different in having a DB instance.

You may find it easier to write a util method that takes a user user_has_discount(request.user) then factor all your checking into that

comment:9 Changed 4 years ago by riccardodivirgilio

  • Resolution duplicate deleted
  • Status changed from closed to reopened

this is what i have done.

maybe you have missed the point. this is not about my application, or the way i found to hack this lack, you asked me for an example.

the point is that this is not a real backend.

the current django behavior is to permit a developer to create a custom user class, but the middleware do not pass the same class if the user in unauthenticated.

according to me, in a running application, it's a mess to have to different kind of classes, depending if the user is authenticated or not.

i'm not here to ask django to solve my problems, i'm are to solve django problems, because my application is alive and running, i'm only contributing for an issue, that (according to me) it's big for deploying a custom user backend.

in an object-driving application, i don't see why i have to write function and put a lot of time getattr(user, "foo") or hasattr(user, "foo"), because it's my app and in my app user has foo attribute, because i have decided that is required, so in this login even the Unauthenticated user must have a foo attribute.

django it's a framework, not an application, developers must be able to decide which field user class must have, and with the current backend developers cannot do that.

please read the backend.py i have attached, it's better to have an attribute in the class and call it using something like "self.user_model.objects.get()" for the same reason inside the ModelAdmin you call self.model and not directly the model itself.

whit this simple approach a developer can set a custom user class and a permission backend but it's still able to use all views and urls without any hack.

please, read the code, they are just a few line of code that can save a lot of problems.

my question is why do you want to set AnoninmousUser as request.user, instead of let developers choose to use django class or a custom class?
why?

Changed 4 years ago by riccardodivirgilio

comment:10 Changed 4 years ago by riccardodivirgilio

i've attached a .diff

the only thing to do then is to change django.contrib.auth.get_user and instead of import directly AnonimousUser return the anonymous user class defined inside the backend.

this change have got no compatibility problems for any running django application, but can save a lot of problems to django developers in the future.

trust me, because i've got a lot of problems for this small issue. i've to write a lot of functions, a lot of getattr, a lot of hasattr, and this is not clean and not readable.

comment:11 Changed 3 years ago by aaugustin

  • Resolution set to duplicate
  • Status changed from reopened to closed

I confirm that introducing a customizable User, Permission, or AnonymousUser model is in the realm of #3011. Some comments on that ticket discuss AnonymousUser specifically.

The fact that #3011 is still open means that the community agrees that Django should let developers use a custom class instead of User and AnonymousUser, and possibly customize other parts of django.contrib.auth. We just haven't figured out a complete solution without unacceptable drawbacks yet.

On a side note, please upload patches in unified diff format (that's what svn diff or diff -u produces) — it's much easier to read in Trac.

Note: See TracTickets for help on using tickets.
Back to Top