tags:

views:

160

answers:

4

I've extended Django's default user class like this:

class CustomUser(User):
 friends = models.ManyToManyField('self', symmetrical=False)

But now I want to use that everywhere instead of the default User class. In my view methods, I have access to request.user but that's an instance of the User class. What's the easiest way to make it return a CustomUser instead?

+1  A: 

I think the quickest solution to your problem would simply be to call CustomUser.objects.get(user=user) (this is assuming user is an attribute in your CustomUser model. What I would do is the following:

class CustomUser(models.Model):
    user = models.ForeignKey(User, unique=True)

So when you get a queryset of CustomUsers, you can filter out the one you want based on using a filter of your user at the request.

Otherwise you can modify the middleware to include CustomUsers instead of users, but I'm not sure exactly how to do that ;)

EDIT: Mark mentioned to me that he would prefer to use inheritence so hes able to use all the custom methods of User, which makes sense and so I found an article to fix this problem nicely.

Here it is.

shawnjan
The problem with using a foreign key instead of python inheritance is that you don't get access to all the custom methods. Maybe there is a way I can query it instead though...
Mark
Ah, I see what you were talking about. I think this link will provide you with exactly what you're looking for!http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/
shawnjan
Yeah, I'm trying that but it doesn't seem to be using my ModelBackend... it's still using the default one, even though I specified `AUTHENTICATION_BACKENDS`...
Mark
`CustomUser.objects.get(user=request.user)` won't work btw, *but* `user = CustomUser.objects.get(pk=request.user.id)` seems to do the trick. Not the optimal solution, but Django and me don't seem to be getting along very well at all anyway, so this is nothing new...
Mark
Really, CustomUser.objects.get(user=request.user) didn't work eh... Strange, I definitely use it in work I've done. Does your CustomUser have a user field?
shawnjan
No, it doesn't... the model I posted in my question is complete (yes, it's only 2 lines).
Mark
+4  A: 

I'm not sure if you can do that exactly, but you can access your CustomUser attributes using the Django user_profile feature.

In your settings.py:

AUTH_PROFILE_MODULE = 'myapp.CustomUser'

In your view:

user_friends = user.get_profile().friends

Check out this link for more info.

hora
I think this requires you to set `User` as a foreign key, rather than inheritance like I'm using...
Mark
This is the correct way to do it.
TM
This is the preferred way to handle your problem. It saves you from having to modify existing modules. Leave django.contrib.auth alone, and make your changes to your own code.
jcdyer
@jcd to me it's arguable if it's a big deal. "preferred" is a matter of personal opinion and taste, especially for a one-person team.
Evgeny
+2  A: 

It is all explained here. request.user problem was solved by using an authentication backend. I implemented a custom user according to the author's instructions and have been happy ever since.

shanyu
I found that and tried it, but I couldn't seem to get it working. IMO, you shouldn't even have to replace the backend.
Mark
What was the problem? I am comfortable with the custom backend, but if you don't want to use it you can write a middleware, as per suggested in one of the comments to that post.
shanyu
This is 'teh win' solution right here. A small amount of glue code and you never have to worry about it again. Everywhere in your app gets your custom User model.
T. Stone
+1  A: 

you can also "monkey patch" the existing User model somewhere in your models.py and it should just work. In your code just keep using the original class.

User.add_to_class('friends',models.ManyToManyField('self', symmetrical=False))
Evgeny
Oh! Wish I knew about that a few days ago. But thanks! I've finished that project so I'm not going to go back and try this right now; I'll just assume this works. Would have been the easiest solution.
Mark
sure, small change though in the syntax (I've used friends=models.ManyToMany) the first time
Evgeny