submit an Ip to post1.py
#main.route('/post1',methods=['GET','POST'])
#login_required
def post1():
Ip=request.form['Ip']
print Ip
return redirect(url_for('.post',Ip=Ip))
then redirect to post.py
#main.route('/post', methods=['GET', 'POST'])
#login_required
def post():
#Ip=request.args['Ip']
form = RepairForm(request.form)
print request.form
if request.method == "POST":
repair = Repair(Ip=form.ip.data,Series=form.series.data,Hostname=form.hostname.data,
ManagerIp=form.managerip.data,Comp=form.comp.data,
Model=form.model.data,Location=form.location.data,Box=form.box.data,
Important=form.important.data,Faultype=form.faultype.data,
Subject=form.subject.data,Body=form.body.data,Classify=form.classify.data,
Status=form.status.data,auth_id=current_user._get_current_object().id,
Owner=current_user._get_current_object().username,)
db.session.add(repair)
db.session.commit()
flash('报修成功')
return redirect(url_for('.index'))
form.ip.data=1
print form.ip.data
form.hostname.data=1
print form.hostname.data
print request.form
form.managerip.data=1
form.comp.data=1
form.model.data=1
form.location.data=1
form.box.data=1
form.important.data=1
form.faultype.data=1
form.classify.data=1
form.status.data=1
return render_template('post.html',form=form)
all test ok,but when I uncomment Ip=request.args['Ip'],then test returns 'The browser (or proxy) sent a request that this server could not understand',
This post points out the Form sending error:
Flask raises an HTTP error when it fails to find a key in the args and form dictionaries. What Flask assumes by default is that if you are asking for a particular key and it's not there then something got left out of the request and the entire request is invalid.
You can't use request.args['Ip']because Flask use a custom dictionary implementation from werkzeug called MultiDict. It has his own get method.
use request.args.get('Ip') solved this error,but do not know the reason because request.args['Ip'] still can get the data.
Related
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)
I have a python web app that carry's out calculations on data you send to it via POST / GET parameters.
The app works perfectly on my machine, but when deployed to openshift, it fails to access the parameters with an error no 32 : Broken pipe
I then used this quickstart repo to just focus on server code and not app code.
Got to differentiate between a POST and GET request and ended there
here's the relevant python code :
#app.route('/', methods=['GET','POST'])
def index():
result = ""
if request.method == "GET":
name = request.form['name'] if "name" in request.form else ""
result = "We received a GET request and the value for <name> is :%s" % name
elif request.method == "POST":
result = "We received a POST request"
else :
result = "We don't know what type of request we have received"
return result
So i just wanna know how i can access the parameters.
Don't use Flask's development server in production. Use a proper WSGI server that can handle concurrent requests, like Gunicorn. For now try turning on the server's threaded mode and see if it works.
app.run(host="x.x.x.x", port=1234, threaded=True)
You can get form data from the POST request via:
name = request.form.get("name")
Refactor:
#app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
name = request.form.get("name")
result = "We received a POST request and the value for <name> is - {0}".format(name)
else:
result = "This is a GET request"
return result
Refer to the official Flask documentation to learn more about the Request object.
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')
I read the following page:
https://docs.djangoproject.com/en/1.2/topics/http/decorators/
Basically, I have a function in a controller that only accepts POST requests. And the documentation on that page allowed me to do that. However, i'm noticing that when the user sends a GET or PUT etc, the response is literally nothing. How can I send a generic error or a 404 page or something?
It doesn't return nothing. It returns a 405 Method Not Allowed HTTP status code. This indicates to the client that the requested method is not allowed (as the name describes).
If you're dead set on returning something else, just don't use the decorator. All it does is test if the requested method is in the allowed list of methods. Just add the following to your view code and you can do whatever you want for each condition:
if request.method in ['GET', 'POST']:
// allowed
else:
// not allowed
I can't remember if it was request.method or not and I don't have Django currently installed on any machines to double-check, but something like this could work.
#require_http_methods(["GET", "POST"])
def my_view(request):
if request.method == 'GET':
# return a 404 or something
# or
if request.method != 'POST':
# return a 404 or something
But shouldn't you be getting your generic 405 - Method not allowed return page if you've only allowed POST for eg. to a certain controller ?
Try this =) Good luck!
from django.http import HttpResponseNotAllowed
def my_view(request):
if request.method != 'POST':
return HttpResponseNotAllowed(permitted_methods=('POST',))
I'm trying to learn more about Flask for a project, and I'm wondering if someone can explain to me why the sample code lists the methods 'GET' and 'POST', when it only ever tries to process a login if the request was 'POST'?
#app.route('/login', methods=['GET', 'POST'])
def login():
error = None
if request.method == 'POST':
if request.form['username'] != app.config['USERNAME']:
error = 'Invalid username'
elif request.form['password'] != app.config['PASSWORD']:
error = 'Invalid password'
else:
session['logged_in'] = True
flash('You were logged in')
return redirect(url_for('show_entries'))
# Note that nowhere do we seem to care about 'GET'...
return render_template('login.html', error=error)
GET and POST methods are both handled by your function.
When GET is used, the login form (login.html) is returned for the user to log in. This is the last line of the function.
When POST is used, the form is validated using provided login/password. After that the user is either redirected to an other page (url for show_entries) or the login form is sent another time with the related error.
You should read 'When do you use POST and when do you use GET?' for more details on why POST is used to process the login form and why GET is used to send it.
return render_template('login.html', error=error) is the handler for GET.
Think about the logic:
if request.method == 'POST':
Check Credentials, Set error method
If no credential errors return the correct redirect
if there were errors in the POST section of code render_template gets those errors, otherwise it gets the None from the beginning of the method. I assume that if error is None in render_template it probably just renders a plain ol' login form.
Note: I've never used flask, but I understand python