Redirect in Django giving 302 response

Viewed 1239

What I am trying to do is prevent an authenticated user from accessing the signup page. This is what I have written.

def validate_request(request):
    if request.user.is_authenticated and request.user.is_active:
        print("Condition approved")
        return redirect("home:home")

def signup_view(request):
    validate_request(request)
    if request.method == "POST":
        form = StudentUserSignupForm(request.POST)
        if form.is_valid():
            user = form.save()
            login(request, user)
            return redirect("https://google.com"). #TODO: Replace it
        else:
            redirect("home:home")
    else:
        print("Got some other method: ", request.method)
        form = StudentUserSignupForm()
    context = {
        "form": form,
    }
    return render(request, "signup_login_form.html", context=context)

When I test and create a new user, it gets created successfully and is redirecting fine. However, the new user created is still able to access the signup page.

I added some quick print statements at the redirect function call inside validate_request function and the output was

<HttpResponseRedirect status_code=302, "text/html; charset=utf-8", url="/">

The URL it was trying to check for is already present and is correct.

I replaced the redirect to https://google.com instead of home:home and it still gave the same response.

The third thing tried was to redirect as soon as the signup_view function is called. That too was failing with the same response with both internal redirect and redirecting to Google.

I have been stuck on this problem for a while. I have gone through answers to similar questions but those didn't seem to help me.

Some more details that might be useful

Project structure is

Website
|
'->Website
   '->urls.py
   '-> ...
   '-> ...
'->Users
   '-> urls.py
'->Home
   '-> urls.py

Content of Website/urls.py is

urlpatterns = [
    path('mdeditor/', include('mdeditor.urls')),
    path('admin/', admin.site.urls),
    path('', include("Home.urls")),
    path('u/', include('Users.urls')),
]

urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Content of Users/urls.py is

app_name = "students"

urlpatterns = [
    path('signup/', signup_view, name="signup"),
    path('login/', login_view, name="login"),
]

Content of home/urls.py is

app_name = "home"

urlpatterns = [
    path('', home_view, name="home")
]

Python==3.8.2 Django==3.2.6

I don't know what I am missing here. It would be really helpful if you guys could point me to my mistake here.

4 Answers

I could have checked authenticated users in view itself. But it would be better to write a custom decorator which you can use in any view. If you want to prevent any view from being accessed by logged in users then you can use the following.

from django.shortcuts import redirect
from functools import wraps
from django.urls import reverse

def redirect_logged_in_users(func):
    @wraps(func)
    def wrapper(request,*args,**kwargs):
        if request.user.is_authenticated and request.user.is_active:
            return redirect(reverse("home:home"))
        return func(request, *args, **kwargs)
    return wrapper

Then you can use this custom decorator in sign_up view

@redirect_logged_in_users
def sign_up(request):
    # function code

It seems you just forgot to use the response of validate_request:

def signup_view(request):
    response = validate_request(request)
    if response:
        return response
    ...

If there is a response object (your redirect), just return that. Otherwise go to the rest of the view.

I had the same problem, but it turns out that I wasn't following the password setup instructions provided to me by the Django registration form.

django instructions on user registration password requirements

Make sure you logout from your admin panel before testing your user CRUD otherwise, Django will redirect you everytime since your have

def validate_request(request):
    if request.user.is_authenticated and request.user.is_active:
        print("Condition approved")
        return redirect("home:home")

I know because I am guilty...

Related