djangodjango-modelsdjango-viewsdjango-authenticationdjango-registration

unable to send argument value from one view to another view in Django


In my login view function, i wanted to know if the user is redirected here after being stopped from accessing a Page

This is basically a Q & A website where user is redirected to login page if he click on write Answer link without signing In

Here is views.py of main app

from django.shortcuts import render
from django.http import request, HttpResponseRedirect, HttpResponse
# import the models 
from .models import Question, Answer, Comment
# import paginator for pagination
from django.core.paginator import Paginator
# import forms
from .forms import Write_Answer_form, CommentForm
# import user
from django.contrib.auth.models import User
# import timezone for update function
from django.utils import timezone
# reverse for efficient url redirecting
from django.urls import reverse
from django.shortcuts import redirect


# Create your views here.

# i have deleted some views functions as they seems irrelavant here


def writeAns(request,questionID):
  # check if the user is authenticated
  if request.user.is_authenticated:    
    # get the Question from ID
    RequestedQuestion= Question.objects.get(id= questionID)
    # check if there is a post request from template
    if request.method == 'POST':
      # get all the form data with post request into a variable
      fom= Write_Answer_form(request.POST)
      if fom.is_valid():
        get_save_form_data(RequestedQuestion, request, fom)
        # make a string url to pass as a arguments
        url= '/detail/'+ str(questionID)
        return HttpResponseRedirect(url)
    else:
      # send blank form to template
      fom= Write_Answer_form()
      data= {'form':fom}
      return render(request, 'writeAns.html', data)
  
  # if user is not authenticated
  else:
    return redirect('login_page',args=["True"])

views.py of authentiCation app ( i want to send redirected value to login_page function )

from django.shortcuts import render
from django.http import request,HttpResponseRedirect
# for user creation & login form
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import authenticate, login, logout
# for user related Queries
from django.contrib.auth.models import User
from django.urls import reverse
from django.shortcuts import redirect

# imports for test purpose
from django.http import HttpResponse

# Create your views here.

# register page 
def register_Page(request):
    if request.method == 'POST':
        form= UserCreationForm(request.POST)
        if form.is_valid():
            form.save()
            username= request.POST['username']
            password= request.POST['password1']
            user= authenticate(request,username=username,password=password)
            login(request,user)
            return HttpResponseRedirect('/')
        else:
            return HttpResponse('Either the user name is not available or you may have filled the form incorrectly')
    else:
        form = UserCreationForm()
        context= {'form':form}
        return render(request,'authentication/register_Page.html',context)

# login page
def login_page(request,redirected=None):
    if request.method == 'POST':
        username= request.POST['username']
        password= request.POST['password']
        # returns user if credentials are valid
        user= authenticate(request, username=username, password= password)
        # check if user var contains the user
        if user is not None:
            login(request, user)
            return redirect(reverse('Home_page'))
        else:
            return HttpResponse('Invalid credentials')
    # check if the user is redirected
    if redirected == "True":
        data= {'warning':"please login first"}
        return render(request,'authentication/login.html',data)
    else:
        return render(request,'authentication/login.html')

# logout Page
def log_out(request):
    logout(request)
    return HttpResponseRedirect(reverse('login_page'))

urls.py of authentiCation

from django.urls import path
from authentiCation import views
 
urlpatterns = [
    path('register/',views.register_Page,name='register_Page'),
    path('login/',views.login_page,name='login_page'),
    path('logout/',views.log_out,name='logout_page'),
]

And here is the Traceback

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/writeAns/5

Django Version: 3.2
Python Version: 3.7.3
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'App_wfi_Community',
 'django.contrib.humanize',
 'askQuestion',
 'authentiCation']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback (most recent call last):
  File "/home/saurav/Documents/programming_Projects/WFI-Community/venv/lib/python3.7/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/saurav/Documents/programming_Projects/WFI-Community/venv/lib/python3.7/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/saurav/Documents/programming_Projects/WFI-Community/App_wfi_Community/views.py", line 114, in writeAns
    return redirect('login_page',args=["True"])
  File "/home/saurav/Documents/programming_Projects/WFI-Community/venv/lib/python3.7/site-packages/django/shortcuts.py", line 41, in redirect
    return redirect_class(resolve_url(to, *args, **kwargs))
  File "/home/saurav/Documents/programming_Projects/WFI-Community/venv/lib/python3.7/site-packages/django/shortcuts.py", line 130, in resolve_url
    return reverse(to, args=args, kwargs=kwargs)
  File "/home/saurav/Documents/programming_Projects/WFI-Community/venv/lib/python3.7/site-packages/django/urls/base.py", line 86, in reverse
    return resolver._reverse_with_prefix(view, prefix, *args, **kwargs)
  File "/home/saurav/Documents/programming_Projects/WFI-Community/venv/lib/python3.7/site-packages/django/urls/resolvers.py", line 694, in _reverse_with_prefix
    raise NoReverseMatch(msg)

Exception Type: NoReverseMatch at /writeAns/5
Exception Value: Reverse for 'login_page' with keyword arguments '{'args': ['True']}' not found. 1 pattern(s) tried: ['login/$']

The error is

NoReverseMatch at /writeAns/5

Reverse for 'login_page' with keyword arguments '{'args': ['True']}' not found. 1 pattern(s) tried: ['login/$']


Solution

  • For some reason people think the shortcut function redirect would send their user to some other view while passing data to it. This is not true.

    According to the documentation the redirect function:

    Returns an HttpResponseRedirect to the appropriate URL for the arguments passed.

    The arguments could be:

    • A model: the model’s get_absolute_url() function will be called.
    • A view name, possibly with arguments: reverse() will be used to reverse-resolve the name.
    • An absolute or relative URL, which will be used as-is for the redirect location.

    By default issues a temporary redirect; pass permanent=True to issue a permanent redirect.

    What is HttpResponseRedirect? Well it is simply a response with a HTTP 302 status code and a url in the Location header indicating that their requested resource has been temporarily moved to the URL given by the Location header.

    Well what if we want to have some data for the user and redirect them somewhere? There are various methods to do that:

    1. Use a GET parameter:
    from django.urls import reverse
    
    # While redirecting
    return redirect("{}?{}".format(reverse("login_page"), "data=True"))
    
    # At receiving view:
    data = request.GET.get("data", False) == "True"
    
    1. Store something in the session [Django docs] for the user:
    # While redirecting
    request.session['data'] = "True"
    return redirect('login_page')
    
    # At receiving view
    data = request.session.get('data') == 'True'