Django: Change url based on result of user authentication

1.6k Views Asked by At

I'm new to django and getting stuck on what I think is a simple issue. I've set up user authentication in my app which is working fine, the problem I'm having is with the url address that appears when my form is submitted. Here is the problem:

The action on my form that takes in a user's login credentials is set to "{% url 'home' %}" which is a reference to /dashboard/home. This is exactly what I want the url to be in the event of a successful login. However, when the login is unsuccessful, I want to stay on the login url, which is /dashboard/login. As you can imagine, what's happening instead is that in the event of an unsuccessful login, the url is still changing to /dashboard/home. I think this is misleading for the user and generally just bad practice, but I don't know how to dynamically change the url depending on the result of the login attempt. How can I change the url to /dashboard/login when the attempt is unsuccessful but keep it as /dashboard/home when it is successful?

My files

HTML template

Truncated to just the form.

        <form method="POST" action="{% url 'home' %}">
            {% csrf_token %}
            <div class="form">
                <label for="email" class="credentials">Email:</label>
                <input type="text" name="email" id="email" size="12" maxlength="30" />
            </div>
            <div class="form">
                <label for="password" class="credentials">Password:</label>
                <input type="password" name="password" id="password" size="12"
                    maxlength="30" />
            </div>
            <div class="submit">
                <input type="submit" name="submit" value="GET STARTED" />
            </div>
        </form>

Views

Excuse all of the print functions, they're a help to a beginner :) I also played with a couple of variables I passed to my template via a context dictionary that I haven't removed from the views yet (e.g.,"login_successful")

def portal(request):
if request.method == 'POST':
    print ("first if was executed")
    form = AuthenticationForm(request.POST)

    if form.is_valid():
        print ("second if was executed")
        username = request.POST['email']
        password = request.POST['password']
        user = authenticate(username=username, password=password)

        if user is not None:
            print("user authenticated")

            if user.is_active:
                print("user active")
                login_successful = 1
                print('login_successful: ',login_successful)
                login(request, user)
                d = (UserFields.objects.filter(userid__exact=username).values())

                d2 = d[0]
                print(d2)
                m = d2["manager"]
                am = d2["apexmanager"]
                print (m)
                print (am)
                if am==True:
                    print ("apex executed")
                    return render(request, 'dashboard/homeApexManager_new.html', {'login_error': login_successful})

                elif m==True:
                    print ("m true executed")
                    return render(request, 'dashboard/homeManager_new.html', {'login_error': login_successful})

                else:
                    print ("m false executed")
                    return render(request, 'dashboard/homeEmployee_new.html', {'login_error': login_successful})

            else:
                print("not active")
                return render(request, 'dashboard/login.html')

        else:
            print ("not authenticated")
            login_error = 1
            print (login_error)
            return render_to_response('dashboard/login.html', {'login_error': login_error})

    else:
        print ("form is not valid")
        login_error=1
        print (login_error)
        return render_to_response('dashboard/login.html', {'login_error': login_error})

else:
    print ("request is not POST")
    return render(request, 'dashboard/login.html', {'form': form})            

Urls

from django.conf.urls import url
from . import views
from django.contrib.auth import views as auth_views

urlpatterns = [
    url(r'^login', auth_views.login,name = 'login'),
    url(r'^home', views.portal,name = 'home'),
        ]
2

There are 2 best solutions below

2
On BEST ANSWER

As AMG mentions in his comment, the RightThing(tm) to do is to handle the form submission (POST) in your login view and then either redirect to the dashbord home url (if the form is valid and the login succeeds) or redisplay the form (without redirection) if the form is invalid or the login fails. As a general rule here's the canonical way to handle form submissions (except for search forms which should use the GET method and never redirect):

def someformview(request, ...): 
    if request.method == "POST":
        # the user submitted the form, let's validate it
        form = SomeFormClass(request.POST)
        if form.is_valid():
            # ok, process the data and redirect the user
            do_something_with(form.cleaned_data)
            return redirect("someapp:anotherview")
        # if form is not valid just redisplay it again
        # so the user gets the error messages
    else:
        # assume a GET request: create an unbound form
        form = SomeFormClass()

   # we either had a GET request or invalid form, 
   # let's display it     
   return render(request, "someapp/someviewtemplate.html", {form:form})
1
On

As i understand from your issue that your form redirect user on user homepage regardless valid form or not.

So you don't need to redirect user using action="{% url 'home' %}" This is mean that when form is submitted page have to redirect user on homepage regardless it successful login or not.

You have to redirect using your view. Below i left example with comments, i hope that it helps you:

def portal(request):
  form = AuthenticationForm(request.POST)
  if request.method == 'POST': # checkout if method POST
    print ("first if was executed")
    if form.is_valid(): #checkout if form is valid
        print ("second if was executed")
        username = request.POST['email']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        return HttpResponseRedirect('/dashboard/home/') #if form is valid, it redirect user on home page
    else:
        return render(request, 'dashboard/login.html', {'form': form}) # if not valid it render this form on the same page
  else: # if method GET we just render the form
    print ("request is not POST")
    return render(request, 'dashboard/login.html', {'form': form}) 

Hope it helps you.

UPDATE

the action is the url where will be redirect the page after form submitted. So if you will use same view as i wrote above, you don't need the action url, just leave it action="."