michaelT
michaelT

Reputation: 1711

Django: Redirect between two apps from views.py

There are two apps: app_user and app_test. app_user contains a login.html (with custom login forms). The login is realized using a POST request in JS, which calls a function api_login in app_user.views.py.

This is my very simple login function (for testing):

def api_login(request):
    # Get post data
    post = json.loads(request.body)
    # Get username and password
    username = post.get('username', None)
    password = post.get('password', None)
    # Returned data object
    data = {
        "success": False,
        "username": username,
    }
    # Username and password
    if username == "" or password == "":
        data['success'] = False
        return JsonResponse(data)
    # Check if input is correct
    user = authenticate(username=username, password=password)
    if user is not None:
        data['success'] = True
        login(request, user)
        # return JsonResponse(data) <-- No data response, there should be a redirect 
        return redirect('app_test:test-home')
    else:
        data['success'] = False
    return JsonResponse(data)

This works well but I want to make a redirect from http://localhost:8000/login/ (included by app_user) to http://localhost:8000/test/ (included by app_test) when the login was successful.

My main url pattern (urls.py).

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('test/', include('app_test.urls'), name='app_test'),
    path('login/', include('app_user.urls'), name='app_login'),
]

Url pattern from app_user

from django.urls import path
from . import views

urlpatterns = [
    path('', views.view_login, name='user-login'),
    path('api/login', views.api_login, name='user-api-login'),
]

Url pattern from app_test

from django.urls import path
from . import views

urlpatterns = [
    path('', views.view_test, name='test-home'),
]

The JS setup:

function login() {
    let url = 'api/login';
    let data = {
        username: inputUsername.getValue(),
        password: inputPassword.getValue()
    };
    let onSuccess = function (data) {
        console.log('>> Success!');
        console.log(data);
    }
    let onServerError = function () {
        console.log('>> onServerError!');
        console.log(data);
    }
    let onError = function () {
        console.log('>> onError!');
        console.log(data);
    }
    request('POST', url, data, onSuccess, onServerError, onError);
}
function request(method, url, data, onSuccess, onServerError, onError) {
    let request = new XMLHttpRequest();
    request.open(method, url, true);
    request.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
    request.setRequestHeader("Content-type", "application/json")
    request.responseType = 'json';
    request.onload = function () {
        if (request.status >= 200 && request.status < 400) {
            // Success!
            console.log('Status: ' + request.status);
            onSuccess(request.response);
        } else {
            console.log('Status: ' + request.status);
            // We reached our target server, but it returned an error
            onServerError(request.response);
        }
    };

    request.onerror = function () {
        console.log('Status: ' + request.status);
        // There was a connection error of some sort
        onError(request.response);
    };
    if (method === 'GET') {
        console.log('>> GET');
        request.send();
    } else {
        console.log('>> POST');
        request.send(JSON.stringify(data));
    }
}

The redirect in api_login does not work using: redirect('test-home') or redirect('app_test:test-home') (for this I added app_name = 'app_test' in app_test.py. So how can I make a redirect in api_login between two apps?

Upvotes: 0

Views: 86

Answers (1)

Achuth Varghese
Achuth Varghese

Reputation: 2451

The response you get for the valid login will be the html page for the url 'app_test:test-home'. You can check that in the browser developer tools. Need to get the JsonResponse for the request even for a valid login. Add the redirect url in the response and redirect using js instead.

Using reverse() to create the redirect url. docs

If you need to use something similar to the url template tag in your code

from django.urls import reverse

def api_login(request):
    # Get post data
    post = json.loads(request.body)
    # Get username and password
    username = post.get('username', None)
    password = post.get('password', None)
    # Returned data object
    data = {
        "success": False,
        "username": username,
    }
    # Username and password
    if username == "" or password == "":
        data['success'] = False
        return JsonResponse(data)
    # Check if input is correct
    user = authenticate(username=username, password=password)
    if user is not None:
        data['success'] = True
        login(request, user)
        data['redirect'] = reverse('test-home') # import reverse from django.urls
        return JsonResponse(data) # return response with the redirect url
    else:
        data['success'] = False
    return JsonResponse(data)

In js redirect checking the response data

if( 'redirect' in data) {
    window.location = data['redirect'];
}

You can add this either in

        if (request.status >= 200 && request.status < 400) {
            // Success!
            console.log('Status: ' + request.status);
            if( 'redirect' in request.response) {
                window.location = data['redirect'];
            }
            onSuccess(request.response);
        }

OR

    let onSuccess = function (data) {
        console.log('>> Success!');
        if( 'redirect' in data) {
            window.location = data.redirect;
        }
        console.log(data);
    }

Upvotes: 1

Related Questions