Redirect from second view - python

Got a real problem here. I have got 2 views in backend and really need to redirect FROM second view
Views like this:
def first_function(request):
""" Here is some stuff """
second_function(request)
return render(request, 'first.html', context)
def second_function(request)
""" Check here something """
if ok:
return
else:
return redirect('/') # this redirect does not work

Your view second_function returns a response. As long as the view doesn't raise an exception, your first_function will continue, whatever the status code of that response.
If you want to return the redirect, then you'll have to assign the result to a status code, then you'll have to assign the result of second_function to a variable, then check the status code.
def first_function(request):
""" Here is some stuff """
response = second_function(request)
if response.status_code == '302':
return response
return render(request, 'first.html', context)
This isn't a good way to structure your code, but I can't suggest an alternative because your code show what you're really trying to do.

Related

Django:How to return nowhere?

(sorry for my bad english)
hello mans.i have a such view in django:
if request.user.is_authenticated:
favelan = get_object_or_404(elan,id = id)
isfav = True
if favelan.favorit.filter(id = request.user.id).exists():
favelan.favorit.remove(request.user)
messages.success(request,'Elan Uluzlulardan Silindi!')
isfav = False
return redirect("/",{'isfav':isfav})
else:
favelan.favorit.add(request.user)
messages.success(request,'Elan Uluzlulara Elave Olundu!')
isfav = True
return redirect("/",{'isfav':isfav})
return redirect('/hesablar/qeydiyyat')
i want this view redirect user nowhere.how i do this?i tried:
reqabspath = request.path
return redirect(reqabspath,{'isfav':isfav})
but its not working.i want redirect user nowhere.please help me.thanks now.
You can use render
from django.shortcuts import render
...
return render(request, 'yourTemplate.html', {'isfav': isfav})
You can redirect to the page on which user was before sending request with return HttpResponseRedirect(request.META['HTTP_REFERER']). So user will stay on same page after request.
from django.http import HttpResponseRedirect
def your_function(self, request):
...
return HttpResponseRedirect(request.META['HTTP_REFERER'])
META['HTTP_REFERER'] stores url of referring page, if any. So you just redirect to it. But be aware, this header is not required, so it would be better to use some default_url, in case browser won't send HTTP_REFERER header. It could be handled like this:
return HttpResponseRedirect(request.META.get('HTTP_REFERER', YOUR_DEFAULT_URL))
So it will redirect to HTTP_REFERER if it exist, and if not, it'll redirect to YOUR_DEFAULT_URL

How to rewrite this Flask view function to follow the post/redirect/get pattern?

I have a small log browser. It retrieves and displays a list of previously logged records depending on user's input. It does not update anything.
The code is very simple and is working fine. This is a simplified version:
#app.route('/log', methods=['GET', 'POST'])
def log():
form = LogForm()
if form.validate_on_submit():
args = parse(form)
return render_template('log.html', form=form, log=getlog(*args))
return render_template('log.html', form=form)
However it does not follow the post/redirect/get pattern and I want to fix this.
Where should I store the posted data (i.e. the args) between post and get? What is the standard or recommended approach? Should I set a cookie? Should I use flask.session object, create a cache there? Could you please point me in the right direction? Most of the time I'm writing backends...
UPDATE:
I'm posting the resulting code.
#app.route('/log', methods=['POST'])
def log_post():
form = LogForm()
if form.validate_on_submit():
session['logformdata'] = form.data
return redirect(url_for('log'))
# either flash errors here or display them in the template
return render_template('log.html', form=form)
#app.route('/log', methods=['GET'])
def log():
try:
formdata = session.pop('logformdata')
except KeyError:
return render_template('log.html', form=LogForm())
args = parse(formdata)
log = getlog(args)
return render_template('log.html', form=LogForm(data=formdata), log=log)
So, ultimately the post/redirect/get pattern protects against submitting form data more than once. Since your POST here is not actually making any database changes the approach you're using seems fine. Typically in the pattern the POST makes a change to underlying data structure (e.g. UPDATE/INSERT/DELETE), then on the redirect you query the updated data (SELECT) so typically you don't need to "store" anything in between the redirect and get.
With all the being said my approach for this would be to use the Flask session object, which is a cookie that Flask manages for you. You could do something like this:
#app.route('/log', methods=['GET', 'POST'])
def log():
form = LogForm()
if form.validate_on_submit():
args = parse(form)
session['log'] = getlog(*args)
return redirect(url_for('log'))
saved = session.pop('log', None)
return render_template('log.html', form=form, log=saved)
Also, to use session, you must have a secret_key set as part of you application configuration.
Flask Session API
UPDATE 1/9/16
Per ThiefMaster's comment, re-arranged the order of logic here to allow use of WTForms validation methods for invalid form submissions so invalid form submissions are not lost.
The common way to do P/R/G in Flask is this:
#app.route('/log', methods=('GET', 'POST'))
def log():
form = LogForm()
if form.validate_on_submit():
# process the form data
# you can flash() a message here or add something to the session
return redirect(url_for('log'))
# this code is reached when the form was not submitted or failed to validate
# if you add something to the session in case of successful submission, try
# popping it here and pass it to the template
return render_template('log.html', form=form)
By staying on the POSTed page in case the form failed to validate WTForms prefills the fields with the data entered by the user and you can show the errors of each field during form rendering (usually people write some Jinja macros to render a WTForm easily)

django message with redirect not displaying

Why messages framework only work with render with context. But in my case i want redirect because the form validation is failed i want here message to display in frontend ..
def user(request):
if form.is_valid():
#do action
else:
messages.error(request, "Your Message")
#return render(request, 'pages/user-account.html') # working fine
return redirect(reverse('frontend.views.user')) # not working
return render(request, 'pages/user.html')
What am missing here ?
Something is not right in your code. !
return redirect(reverse('frontend.views.user')) # not working
You told that you redirect. But redirecting to where ? 'frontend.views.user' will get you to the same page but again with different request object. Make your view redirect to another function or use the working one render with request.

Django - Simple redirect to requested URL

I'd like to do that, but this
return HttpResponseRedirect(request.path_info)
yields a redirect loop. I suspect it's because the request object is the website you're on at that time.
Whole function
def permit(request, pk):
if int(request.user.id) == int(pk):
return HttpResponseRedirect(request.path_info)
else:
return render_to_response('forbidden.html')
The user has clicked a link on a webpage. pk is the regx search term in urls.py. I want this to redirect to the page the user clicked on if the user is authorized, not the page he is currently on.
The problem is that as soon as the user is "redirected", the function permit is called. The if statement is true (since it is the authenticated user) and the redirect happens again... To prevent this loop, only redirect, if there was a post request:
def permit(request, pk):
if request.POST:
if int(request.user.id) == int(pk):
return HttpResponseRedirect(request.path_info)
else:
return render_to_response('forbidden.html')
## Return your login page here.

Flask login_required + next url params

I have a protected view in my app which just accepts POST requests.
#app.route("/booking", methods=("POST", ))
#login_required
def booking():
arg1 = request.form.get("arg1")
arg2 = request.form.get("arg2")
When an unauthorized user tries to access this view, I want them to
login and then be redirected here.
Right now, my login view looks like this:
#app.route("/login", methods=("GET", "POST"))
#login_required
def login():
do_login()
return redirect(request.args.get('next') or url_for('home'))
So what ends up happening is a POST request to /booking (which is the
"next" parameter) and I get a NOT ALLOWED error.
The problem is that login() makes a GET request to booking(). I can
get around that, but I am not sure how to retrieve the original POST
form arguments from /booking? Any ideas to get round that?
I would solve this by pulling the data and putting it in the session. You can remove the #login_required decorator and check this in the function using current_user.is_authorized. See Flask Sessions and Flask Login.
Something like this might work for you, I didn't test it:
from flask import session
from flask_login import current_user
#app.route("/booking", methods=("POST", ))
def booking():
if not 'arg1' in session.keys() and not 'arg2' in session.keys():
session['arg1'] = request.form.get("arg1")
session['arg2'] = request.form.get("arg2")
# Now the data will persist in the session
if current_user.is_authorized:
# Do what you need...
else:
# Redirect to login, session will persist
Why would you only use POST in the booking view ? You are probably rendering a form which should also allow GET.
#app.route("/booking", methods=['GET','POST'])
#login_required
def booking():
# render the form. something like
form = BookingForm()
# Check if POST
if request.method == 'POST':
# process the form now and do whatever you need.
return redirect(url_for('index'))
# code below will run if not POST. You should render the template here
return render_templte('booking.html')

Categories

Resources