Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert request.user into a proxy auth.User class?

I have the same conundrum as presented in this question, but applied to Django's auth.User.

I have this proxy model:

class OrderedUser(User):
    def __unicode__(self):
        return self.get_full_name()

    class Meta: 
        proxy=True
        ordering=["first_name", "last_name"]

And some of my other models use an OrderedUser instead of a django.contrib.auth.models.User as field types.

In my views I then use the request.user to populate a field and - as expected - get an error:

'Cannot assign "<User...>": <field> must be a "OrderedUser" instance'

I could just do OrderedUser.objects.get(request.user.id), but that is an extra hit to the database.

So, how to convert a base model class into its proxied class?

like image 219
cethegeek Avatar asked Jun 09 '10 14:06

cethegeek


People also ask

What is a SimpleLazyObject?

return wrapped class SimpleLazyObject(LazyObject): """ A lazy object initialized from any function. Designed for compound objects of unknown type. For builtins or objects of known type, use django.utils.functional.lazy. """ def __init__(self, func): """ Pass in a callable that returns the object to be wrapped.

What is Auth_user_model?

AUTH_USER_MODEL is the recommended approach when referring to a user model in a models.py file. For this you need to create custom User Model by either subclassing AbstractUser or AbstractBaseUser.

What is Get_user_model in Django?

get_user_model () Instead of referring to User directly, you should reference the user model using django.contrib.auth.get_user_model() . This method will return the currently active user model – the custom user model if one is specified, or User otherwise.

What is request user in Django?

user is User model object. You cannot access request object in template if you do not pass request explicitly. If you want access user object from template, you should pass it to template or use RequestContext. It depends upon what you set .


2 Answers

It's another database hit, but this will work:

OrderedUser.objects.get(pk=request.user.pk)

Edit You could try:

o = OrderedUser()
o.__dict__ = request.user.__dict__
like image 200
Daniel Roseman Avatar answered Nov 15 '22 07:11

Daniel Roseman


I couldn't get the copy dict method to work on Python 2.7.4 and Django 1.6. I didn't trace it all the way down, but I think it had something to do with it being a lazy object.

What worked for me:

request.user.__class__ = OrderedUser

It avoids the database call and gives access to the base auth stuff and all my extended behaviors.

To make the request.user act like the proxy class always, I put the assignment in middleware after the authentication middleware and before any of my apps could reference it. Since the middleware is called on every request, make sure the user is authenticated before setting the class. Using your example, here is how the middleware code might look:

from yourapp.models import OrderedUser

class OrderedUserMiddleware():
    def process_request(self, request):
        if hasattr(request, 'user') and request.user.is_authenticated():
            request.user.__class__ = OrderedUser

And remember to register the middleware after the authentication:

MIDDLEWARE_CLASSES = [
    # ...middleware from the guts of Django, none of your middle wares yet...
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    # ...more middleware from the guts of Django, none of your middlewares yet...
    'yourapp.middleware.OrderedUserMiddleware',
    # ...more middleware from you other middlewares...
]
like image 36
FlyDanoFly Avatar answered Nov 15 '22 07:11

FlyDanoFly