Search code examples
djangohttp-redirectregistrationreverseprofile

Redirect a Django view


After a user logs into my app, I would like to redirect the person to their profile.
However, I keep getting this error:

TypeError at /app/url/username/
profile() got an unexpected keyword argument 'username'

Here is the model:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    profile_picture = models.ImageField(upload_to='profile_images', blank = True)

        def __str__(self):
            return self.user.username

Here is the view where the user will log in and that will then redirect the user to the profile:

def user_login(request):


    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')

        user = authenticate(username=username, password=password)

        if user:
           if user.is_active:
               login(request, user)

               url = reverse('profile', kwargs={'username': username})
            return redirect(url)

           else:
               return HttpResponse("Please login.")

         else:
             print("Invalid login details: {0}, {1}".format(username, password))
             return HttpResponse("Invalid login details supplied.")

     else:
         return render(request, 'reviews/login.html', {})

Here is the view for the user profile:

@login_required
def profile(request, user):
    user = UserProfile.objects.get(user = request.user)
    return render(request, 'reviews/profile.html', {'username':username})

Here is the url pattern:

url(r'^profile/(?P<username>\w+)/$', views.profile, name='profile')

Can someone tell me how to redirect the logged user to their profile?

Tried both approaches suggested so far. I received this error for both of them:

UserProfile matching query does not exist.

Here is the traceback:

Environment:


Request Method: GET
Request URL: http://localhost:8000/app/profile/username/

Django Version: 1.8.3
Python Version: 3.4.3
Installed Applications:
('grappelli',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'reviews',
 'compressor',
 'cloudinary')
 Installed Middleware:
 ('django.contrib.sessions.middleware.SessionMiddleware',
  'django.middleware.common.CommonMiddleware',
  'django.middleware.csrf.CsrfViewMiddleware',
  'django.contrib.auth.middleware.AuthenticationMiddleware',
  'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
  'django.contrib.messages.middleware.MessageMiddleware',
  'django.middleware.clickjacking.XFrameOptionsMiddleware',
  'django.middleware.security.SecurityMiddleware')


Traceback:
File "/var/www/nurse/lib/python3.4/site-   packages/django/core/handlers/base.py" in get_response
132.                     response = wrapped_callback(request,   *callback_args, **callback_kwargs)
File "/var/www/nurse/lib/python3.4/site-  packages/django/contrib/auth/decorators.py" in _wrapped_view
22.                 return view_func(request, *args, **kwargs)
File "/var/www/nurse/nurseapp/reviews/views.py" in profile
165.      user=UserProfile.objects.get(user = request.user)                       
File "/var/www/nurse/lib/python3.4/site-packages/django/db/models/manager.py" in manager_method 127.                   return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/var/www/nurse/lib/python3.4/site-packages/django/db/models/query.py" in get 334.                 self.model._meta.object_name

Exception Type: DoesNotExist at /app/profile/username/
Exception Value: UserProfile matching query does not exist.

Solution

  • I see two possible issues in your code:

    First one, in user_login function when creating url for redirection using reverse(), you should pass username value in args instead of kwargs:

    url = reverse('profile', args=(username,))
    

    Second thing, it seems you named the parameter in profile url as username which means it will be passed into corresponding view function with the same name so you should rename user as username in view and update your logic as follows:

    @login_required
    def profile(request, username):
        p = UserProfile.objects.get(user__username=username)
        return render(request, 'reviews/profile.html', 
            {'username': username, 'user': p.user, 'profile': p})
    

    Please note that, for each User object, there must be one UserProfile corresponding to it. If you don't create a UserProfile object after new user signs up, you can try sending User object to your template instead:

    @login_required
    def profile(request, username):
        user = User.objects.get(username=username)
        return render(request, 'reviews/profile.html', 
            {'username': username, 'user': user})
    

    It is a bad practice but, in user_login view, you can try creating UserProfile if not exists once user logs in:

    def user_login(request):
        ...
        user = authenticate(username=username, password=password)   
        if user:
            if user.is_active:
                UserProfile.objects.get_or_create(user=user)
                ...
        ...