Redirect not able to send response - python

I'm using redirect in Django to send the user to another page but it is not able to do so.
views.py
def func1(request):
if not request.user.is_authenticated():
return render(request, 'login/login/login.html')
else:
if request.method == "POST":
return redirect('base:func2')
return render(request, 'base/home/index.html')
def func2(request):
if not request.user.is_authenticated():
return render(request, 'login/login/login.html')
else:
if request.method == "POST":
....
return render(request,
'bla_bla_bla.html',
{'location': location})
elif request.method == 'GET':
print('COntrol is here')
some_details_form = SomeDetailsForm()
return render(request, 'some_url/index.html',
{'some_details_form': some_details_form})
urls.py
app_name = 'base'
url(r'^another_url/$', views.func2, name='func2'),
url(r'^some_url/$', views.func1, name='func1'),
base/home/index.html
<div class="button" onclick="clicked_it()">
<span id="forward"> Go Further </span>
</div>
index.js
function clicked_it()
{
$.post( "/base/some_url/");
};
So the control does go to func2 since I can see the print statement output COntrol is here but I don't see that the func2 is able to render the page in the return statement. Where is the control getting stuck?

The whole point of using Ajax is that it overrides the browser navigation handling. If you want your Ajax to redirect, you need to do it in js - or, don't use Ajax at all.

redirect either needs the relative or absolute url that you need to redirect to.
You need to use django reverse url resolver
from django.core.urlresolvers import reverse
def func1(request):
if not request.user.is_authenticated():
return render(request, 'login/login/login.html')
else:
if request.method == "POST":
return redirect(reverse('base:func2'))
return render(request, 'base/home/index.html')

Related

Previous pages display after logout and session deleted

Login code:
def login(request):
if request.method == 'POST':
user = request.POST['uname']
password = request.POST['psw']
log = User.objects.filter(username=user, password=password)
if log:
request.session['login'] = True
return HttpResponseRedirect('/page')
else:
return render(request, 'login.html')
else:
return render(request, 'login.html')
Logout code:
del request.session['login']
request.session.modified = True
return HttpResponseRedirect("/")
After logout when I move back I am able to see the previous pages but as soon as I refresh the page it redirects me to login page and restricts me to access previous page.
def page(request):
if not request.session.get('login', False):
return HttpResponseRedirect("/tnp_admin/")
else:
#access page
How to not display previous pages after logout and why is session working only after refreshing page?
You can either use if user.is_authenticated in the view or import login_required property from django.contrib.auth.decorators and put #login_required on top of your view for that template.

Passing context to a Response and using it in a view

I am working on a web app and I want to use HttpResponse or HttpResponseRedirect instead of render. But I dont know hoe to pass context in response as it does not have context parameter like render. And also how to use the passed context in the url or view ?
Here is my view:
#login_required
def view_task_description(request):
if request.method == 'POST':
task_description = GetTaskDescription(data=request.POST, user=request.user)
if task_description.is_valid():
obj = GetTaskDescription.get_task_description(task_description)
return render(request, 'todoapp/task_desc.html', context={'description': obj[0].description})
return render(request, 'todoapp/select_task_description.html', context={'view_tasks': GetTaskDescription(user=request.user)})
I want to use Redirect or ResponseRedirect with the context instead of the render that I am returning if my form is valid. Basically render still shows the response as a POST method and I want the response to be a GET. How can I do so ? Thanks.
You can simply create a new view for that. Then link it to the existing view using redirect. For example:
# view
from django.shortcuts import get_object_or_404
#login_required
def get_task_description(request, pk):
obj = get_object_or_404(TaskDescriptionModel, pk=pk)
return render(request, 'todoapp/task_desc.html', context={'description': obj.description})
# url
url(r'^some_path/(?P<pk>[0-9]+)/$', get_task_description, name="get_task_description")
# linking to existing view
from django.shortcuts import redirect
...
if task_description.is_valid():
obj = GetTaskDescription.get_task_description(task_description)
return redirect('get_task_description', pk=obj[0].pk) # <-- Pointing the new view

Calling "return render" won't work when calling from an outside method (Django, views.py)

Very first question here.
I am having trouble creating a reusable method to use in my views.py file for handling user authentication. I have created and imported a utils.py file that looks like this:
from django.shortcuts import render
from django.contrib.auth.forms import AuthenticationForm
def check_log_in(request):
username = None
if request.user.is_authenticated():
user = request.user
if user.is_staff == False:
message = "You are not an authorized staff member."
form = AuthenticationForm()
context = {'form': form,
'message': message}
return render(request, 'obits/login.html', context)
else:
message = "Please log-in to add a new record."
form = AuthenticationForm()
context = {'form': form,
'message': message}
return render(request, 'obits/login.html', context)
If I put this same code directly into my view, it works just fine, but now that I have it as a separate method, it doesn't break at the return render and instead continues on through the code. I used print statements to test that it was calling correctly and it is. Here is the current view:
def new(request):
check_log_in(request)
if request.method == 'POST':
if form.is_valid():
#code, yada, yada, context
return render(request, 'obits/detail.html', context)
else:
#code, yada, yada, context
return render(request, 'obits/new.html', context)
else:
#code, yada, yada, context
return render(request, 'obits/new.html', context)
In this current set-up, it will detect that the user is not logged-in, but still just go right ahead and display the new.html page, rather than redirecting to log-in. But if I cut and paste the exact code contained in check_log_in instead of just calling it, it works fine.
Any ideas? Thank you in advance!
If you return from check_log_in() but do nothing with the returned value, execution of your new() view is going to continue.
You need to check if check_log_in() returned something and if it did, return that from your new() view:
def new(request):
response = check_log_in(request)
if response is not None:
return response
if request.method == 'POST':
# rest of your code

DJANGO - Redirect to different page from POST with data

I am trying to have a simple form that once filled, will direct to a different webpage or remain on the same page if invalid. The page should have a text box and submit form and once a user enters anything it should direct you to a separate page.
My directory structure is as follows:
appName/
app/
forms.py
urls.py
views.py
templates/
app/
goodbye.html
name.html
library.html
thanks.html
appName/
settings.py
urls.py
My app/urls.py is as follows:
from django.conf.urls import url
from . import views
app_name = 'app'
urlpatterns = [
url(r'^$', views.index2, name = 'index'),
url(r'^hello/$', views.hello, name = 'hello'),
url(r'^goodbye/$', views.goodbye, name = 'goodbye'),
#url(r'^library$', views.library, name = 'library'),
url(r'^library/$', views.library, name = 'library'),
url(r'^library/(?P<book_id>[0-9]+)/$', views.book, name = 'book'),
url(r'^getname/$', views.get_name, name = 'get_name'),
url(r'^your-name/$',views.get_name, name='get_name'),
url(r'^thanks/$',views.say_thanks,name='thanks'),
#url(r'^thanks/(?P<name_id>[a-zA-Z]+)/$', views.say_thanks,name='thanks'),
]
My forms.py is :
from django import forms
class NameForm(forms.Form):
your_name = forms.CharField(label = 'Your name', max_length=100)
My app/views.py is:
from django.http import HttpResponse
from django.template import loader
from django.shortcuts import render
from django.http import HttpResponseRedirect
#forms
from .forms import NameForm
# Create your views here.
def index2(request):
return HttpResponse("hello world")
def hello(request):
text = """<h1>Welcome to my app! </h1>"""
return HttpResponse(text)
def goodbye(request):
template = loader.get_template("app/goodbye.html")
context = {
'output' : 'This is output from goodby views.py request handler'
}
return HttpResponse(template.render(context,request))
def library(request):
template = loader.get_template("app/library.html")
context = {
'output' : 'Welcome to the libary!!'
}
return HttpResponse(template.render(context, request))
def book(request, book_id):
return HttpResponse("You're looking at book %s. " % book_id)
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
#process the data in form.cleaned_data as required
locationGo = "/thanks/"
template = loader.get_template("app/thanks.html")
return HttpResponse(template.render({'name':'name'},request))
else:
form = NameForm()
template = loader.get_template("app/name.html")
context = {'form': form}
return HttpResponse(template.render(context, request))
def say_thanks(request):
template = loader.get_template("app/thanks.html")
return HttpResponse(template.render({'name': 'name'},request))
My templates include:
name.html :
<form action = "/getname/" method = "post">
{% csrf_token %}
{{ form }}
<input type = "submit" value = "Submit" />
</form>
goodbye.html
<h1>Goodbye to Template Romance</h1>
Go Back
thanks.html
Thanks {{name}}!
What I would like is for:
A user to visit to : website.com/getname/ to show the name.html file (which it does)
If a user hits submit to stay on the same page (website.com/getname/) (which it doesn't - it gives: ValueError at /getname/ ->The view app.views.get_name didn't return an HttpResponse object. It returned None instead.
If a user enters in the submit field, to be redirected to website.com/thanks/ (which it sort of does. It currently loads the thanks.html template, but the URL stays on website.com/getname/)
Inside the get_name(request): function, the POST and GET if...else doesn't seem to be firing based on the Submit button, and it doesn't seem to be loading the correct page, OR change the current URL address once it gets processed. I have tried using HttpRedirect() which works, however, I would also like to pass the forms data (which is another issue).
Any suggestions would be a big help!
Your first problem is that you are not returning a response when the request method is post and the form is invalid. You can fix that by changing the indentation of your view, so that you always return a response at the end of your view.
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
...
else:
form = NameForm()
template = loader.get_template("app/name.html")
context = {'form': form}
return HttpResponse(template.render(context, request))
If you want to redirect to the /thanks/ view, then you can use the redirect shortcut.
if form.is_valid():
return redirect('thanks')
Note that it isn't possible to redirect and pass the form data (see this question for an explanation). You should do any processing you want with the data before redirecting. You could use the messages framework to create a message 'Thanks <name>' before redirecting.
This works because you have name='thanks' in your url pattern.
You can simplify your views by using the render shortcut. Instead of
template = loader.get_template("app/name.html")
context = {'form': form}
return HttpResponse(template.render(context, request))
you can simply do:
return render(request, "app/name.html", context)
Remember to add the imports for the shortcuts:
from django.shortcuts import redirect, render

Post method not working after redirect in Django

I am trying to create a system where certain pages can't be accessed unless the request is from a specific location. I currently have everything working except after the location is checked and the request is redirected to the next view, the form on that next view isn't posting properly. It's still trying to post the location data form.
You'll see what I mean more in my views.py:
def add(request):
if request.method == 'POST':
form = StudentModelForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
else:
form = StudentModelForm()
context_data = {'form': form}
return render(request, 'add.html', context_data)
def location_check_add(request):
if request.method == 'POST' and 'lat' in request.POST:
user_lat = request.POST.get('lat')
user_lon = request.POST.get('lon')
if good_location(user_lat,user_lon):
return add(request)
else:
return render(request, 'location.html')
return render(request, 'checking.html')
So I'm trying to redirect to the add() view if good_location is true. It redirects properly but then when a user tries to post the form on add.html django thinks it's submitting the form in location_check_add again.
Edit: Adding urls.py for reference
import users.views
urlpatterns = patterns('',
url(r'^$', users.views.index, name = 'index'),
url(r'^admin/', include(admin.site.urls)),
url(r'^add/', users.views.location_check_add, name = 'add'),
)
You need to redirect, not just call the view.
if good_location(user_lat,user_lon):
return redirect('add')
Alright! After a lot of documentation searching and googling I found out about Django's sessions feature. Documentation here:
Documentation
In the end my code ended up looking like:
def add(request):
if request.session.get('at_work', False):
if request.method == 'POST':
form = StudentModelForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
else:
form = StudentModelForm()
context_data = {'form': form}
return render(request, 'add.html', context_data)
else:
return redirect(location_check_add)
def location_check_add(request):
if request.method == 'POST' and 'lat' in request.POST:
user_lat = request.POST.get('lat')
user_lon = request.POST.get('lon')
if good_location(user_lat,user_lon):
request.session['at_work'] = True
return redirect(add)
else:
return render(request, 'location.html')
return render (request, 'checking.html')
Basically I just passed around the session variable "at_work" to make sure the location was correct before rendering the page in the add() view. Then I was able to use the regular redirect function since I could have a url directed at add() in urls.py without people getting around the location check.

Categories