0

I'm working on an app that has three "profile" models types. Each of these models has a foreign key to the contrib.auth.models User model.

I would like to have a single sign on for each model type and provide a redirect via classmethod depending on which "profile" model type is related to the logged in user.

Here's some pseudo-code to illustrate what I would like to do:

from django.contrib.auth import authenticate, login
from django.http import HttpResponse, HttpresponseRedirect

from lib.forms import Loginform #extends the built-in AuthenticationForm

def login_user(request):
    if request.method == 'POST':
        form = LoginForm(data=request.POST)
        if form.is_valid():
            cleaned_data = form.cleaned_data
            user = authenticate(username=cleaned_data.get('username'), \
                password=cleaned_data.get('password'))
            if user:
                login(request, user)

                #Determine the content type of the model related to the user
                #get the correct redirect value from an @classmethod
                #called: after_login_redirect for that type and...

                return HttpResponseRedirect(klass.after_login_redirect())
        else:
            response = form.errors_as_json()
            return HttpResponse(json.dumps(response, ensure_ascii=False), \
               mimetype='application/json')

Is it possible to leverage the ContentTypes framework to do this? or am I better off just writing a class resolver that loops over an array of the "profile" classes? I'm not seeing a way I can do this with ContentTypes from the User class, unless someone knows a workaround.

Thanks in advance, Brandon

Brandon Taylor
  • 33,823
  • 15
  • 104
  • 144
  • I found this article: http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/ which I'm going to see if I can modify to suit my needs. – Brandon Taylor Mar 17 '11 at 21:48

1 Answers1

1

[SOLVED]
So, what I ended up doing was creating a UserContentType junction model that looks like this:

from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType

class UserContentType(models.Model):
    user = models.ForeignKey(User)
    content_type = models.ForeignKey(ContentType)

Then, I made a pre-save signal to fire a get or create if the instance of one of the three "profile" models I have doesn't have an id:

from django.contrib.contenttypes.models import ContentType

from lib.models import UserContentType

def set_content_type_for_user(sender, **kwargs):
    instance = kwargs.get('instance')
    content_type = ContentType.objects.get_for_model(instance)
    user = instance.user
    if not instance.id:
        user_content_type, \
            created = UserContentType.objects.get_or_create(user=user, \
            content_type=content_type, \
            defaults={'user' : user, 'content_type' : content_type})

Then, in my custom login view which is posted to via ajax, I can get the content type associated with the User instance and get the URL to redirect to from the 'after_login_redirect()' classmethod on that content type. :)

def login_user(request):
    if request.method == 'POST':
        form = LoginForm(data=request.POST)
        if form.is_valid():
            cleaned_data = form.cleaned_data
            user = authenticate(username=cleaned_data.get('username', ''),
                                password=cleaned_data.get('password', ''))
            if user:
                login(request, user)
                user_content_type = UserContentType.objects.get(user=user)
                redirect_path = 
                   user_content_type.content_type.\
                    model_class().after_login_redirect_path()
                response = {'redirect_path' : redirect_path}
        else:
            response = form.errors_as_json()
        return HttpResponse(json.dumps(response, \
            ensure_ascii=False), mimetype='application/json')

This way, I don't have to monkeypatch User. I hope this helps someone out. If there's a way I can improve on this, I'd love to hear some ideas.

Thanks, Brandon

Brandon Taylor
  • 33,823
  • 15
  • 104
  • 144