Flask form data empty [duplicate] - python

This question already has answers here:
Sending data from HTML form to a Python script in Flask
(2 answers)
Closed 1 year ago.
I've created a form with flask. This is the python code that handles the requests that come from this form:
#app.route("/submitclips/", methods=['GET', 'POST'])
def submitclips():
print(request)
print(request.method)
result = request.form.to_dict(flat=False)
print(result)
print(request.data)
HTML code:
<form action="/submitclips" method="POST">
<input type="hidden" name="taskpath" value="paththotask">
<table>
<th>Video</th>
<th>Mute</th>
<th>Delete</th>
<th>Keep</th>
<tr>
<td>
<video width="320" height="240" controls>
<source src="videosource.mp4" type="video/mp4">
</video>
</td>
<td>
<input type="radio" id="name$mute" name="name" value="mute">
</td>
<td>
<input type="radio" id="name$delete" name="name" value="delete">
</td>
<td>
<input type="radio" id="name$keep" name="name" value="keep" checked>
</td>
</tr>
</table>
<input type="submit">
</form>
This is a table and has more than one row, I changed the values to make it more readable. I guarantee that all names are unique where they are supposed to be unique though.
It has some code below it, but it crashes there because the form seems to be empty. I have checked the HTML and it's all correct, all inputs have a name. I also recorded the network traffic on google chrome to test this and I can see that all data in the form is present in the request data. So I'm pretty sure it's correct on the front-end. The problem is that it just doesn't show up in this method. In the code you can see several print statements and all of these show me empty data and not the data that I could see in my chrome browser. The method is GET, I don't know if it should be GET. In HTML I selected it to be a POST method, but if I remove the GET option from the python code, it gives me a "method not allowed" error.
I don't know what to do, this is some older code that used to work on my windows machine. I didn't change anything about it, but now I'm working on linux and it's completely broken, none of the forms work, it's all empty data.

Here you have mentioned that the endpoint /submitclips has methods GET and POST. It means that whenever i hit the url "baseurl/submitclips" then this function will be executed. Inside the function you have not specified for which method you will have what response, i.e if i call the endpoint using GET or POST you will process it the same way. This is not a good practice. I suggest you put something like :
if request.method == 'POST' or if request.method == 'GET' to separate the execution based on the type of method.
Now coming to the HTML, you must have the HTML from where you are sending the request to the server. If that data is coming from a form, then as part of the form you can add two attributes,
<form method="post"> and <form action="/submitclips"> to specify that on submit of this form,you will be sending the form data through POST method to the "/submitclips" url. It will look like this.
<form method="post" action="/submitclips"">
For the Server side,
def submitclips():
if request.method == 'POST' :
print(request)
print(request.method)
result = request.form.to_dict(flat=False)
print(result)
print(request.data)
It should work after that.

I have found the error. My HTML code would submit the form to "/submitclips" while the python code received requests from "/submitclips/". I don't know why this is wrong though, the tutorial that I followed for flask told me specifically that putting a slash at the end meant that it could receive requests from both "/submitclips" and "/submitclips/". This also worked earlier on my windows machine, but doesn't work anymore on my linux machine. I'm glad it's solved, but if anyone has an explanation for why this is wrong, feel free to answer.

Related

Redirect user in Telegram Bot to an external link with POST request

Since I'm new to this POST/GET HTTP stuff, I might be getting things wrong, that's why I'll put my question in 2 ways. Maybe one way will be better than the other :)
I'm developing a Telegram Bot using PyTelegramBotAPI, and it needs to include an online payment.
For the online payment I need the user to follow a link with POST method (it's an external link + I need to pass form data), but that's what causes difficulties for me.
I.
In my code I perform the following:
req = requests.post(url=url, data=data)
Where url is the URL of the website to which the client must be redirected, and data is the data that it needs to pass with the POST request when redirecting.
It works fine as a request in Python, but obviously it can't redirect the client to the website needed.
I tried to generate a URL and pass it to the client using
url = url + urlencode(data=data)
Where url is again the URL of the website. But in this case the website tells me that the method used is incorrect. I guess the link becomes a GET request, instead of a POST request.
How can I redirect the client to that link with POST method?
II.
Another way of putting this question is this:
The company which processes the online payments requires them to be performed using the following HTML form:
<form action=”https://securesandbox.webpay.by/” method="post">
<input type=”hidden” name=”*scart” >
<input type=”hidden” name=”wsb_storeid” value=”11111111”>
<input type=”hidden” name=”wsb_order_num” value=”ORDER-12345678”>
<input type=”hidden” name=”wsb_currency_id” value=”BYN”>
<input type=”hidden” name=”wsb_version” value=”2”>
<input type=”hidden” name=”wsb_seed” value=”1242649174”>
<input type=”hidden” name=”wsb_signature” value=”124264917411111111ORDER-123456781BYN10123456”>
<input type=”hidden” name=”wsb_test” value=”1”>
<input type=”hidden” name=”wsb_invoice_item_name[0]” value=”Товар 1”>
<input type=”hidden” name=”wsb_invoice_item_quantity[0]” value=”2”>
<input type=”hidden” name=”wsb_invoice_item_price[0]” value=”10”>
<input type=”hidden” name=”wsb_total” value=”10”>
<input type="submit" value="Купить">
</form>
This would work well if I used HTML pages, but since my web app is a Telegram Bot, hence this wouldn't work. Therefore I need to generate this HTML form automatically in Python (namely, I need to change the "value" fields for every payment).
How can I imitate this HTML form in my Telegram Bot and redirect the client after some trigger?

Converting Output to HTML

I am making this program:
name = input("Enter your name: ")
age = input("Enter your age: ")
position = input("Your position in class: ")
print("I am",name,". I am",age,"years old. This time I got",position,"position
in my class.")
This outputs
I am Python Man . I am 13 years old. This time I got 1st position in my
class.
How can I enter this output into html, guys?
If you were to put...
I am Python Man . I am 13 years old. This time I got 1st position in my
class.
Into a .html file then load it, it'd work fine. If you want to format it properly with tags directly from the python file, you could change your print() line to, for example...
print("<p>I am",name,". I am",age,"years old. This time I got",position,"position
in my class.</p>")
There is several ways, and depends on what you really want to achieve, so I'll explain couple of options you have:
you can add any HTML tags you want in the string "as it's already
HTML that doesn't have any tags to format it" but you will have to
escape special characters that may break your HTML using built-in
Module " html"
you can also use third-party modules such as this which can generate HTML for you, and it's usage described briefly in the link.
The choice is simple if you have HTML knowledge and want to customize your HTML go for the first option, if not or you want easy solution go for the module.
I'm going to cut you some slack here. The text you have is already perfectly valid HTML. I think you actually want to display the text in a browser (jumping a few steps ahead). You will need a web framework for that; I'm using Flask here, but there are many, with Django being the other major framework (that takes a little more effort to set up).
from flask import Flask, request
app = Flask(__name__)
#app.route('/')
def homepage():
return("""<table>
<thead>
<th>Name</th>
<th>Age</th>
<th>Position</th>
<th></th>
</thead>
<tbody>
<form method ="post" action="{{ url_for('submit_answer') }}">
<input type="hidden" value="{{ csrf_token() }}" name="csrf_token">
<tr>
<td><input type="text" name="my_name" value=""></td>
<td><input type="text" name="my_age" value=""></td>
<td><input type="text" name="my_position" value=""></td>
<td><input type="submit" value="Submit"></td>
</tr>
</form>
</tbody>
</table>""")
#app.route('/submit_answer', methods=["GET", "POST"])
def submit_answer():
req = request.form.to_dict()
return "Hello {}, aged {}, your position is {}".format(req['my_name'],
req['my_age'],
req['my_position'])
if __name__ == '__main__':
app.run()
Run this and then type 127.0.0.1:5000 in the browser. There's a lot going on here, but hopefully enough to inspire you and keep you interested. You'll need to Google a lot. You can find more in the quickstart guide for Flask.

Flask - getting a value from a Vue MultiSelect Element

I have a Vue-multiselect, as in this example (not mine)
https://jsfiddle.net/gmsa/04jvjuv3/
I'm trying to get the value in the multi select element and POST it back to my Flask app.
HTML
<form action="" method="POST">
<multiselect id="multi", name = "multi" :multiple="true" :hide-selected="true" :selected="selected" :options="options" :taggable="false" #update="updateSelected"></multiselect>
<button type="submit" value="l1" >Load</button>
</form>
Flask
if request.method == 'POST':
print request.form.getlist('multi')
#prints an empty list
print request.form['multi']
#hits a bad request error
I've been klutzing about with this for a long time now - why can't I get the value from the form element?
The thing is that vue-multiselect is meant to be handled using pure javascript. So, you could just use the solution implemented by the user in that issue.
In HTML:
<input style="display: none;" :value="selected" name="multiselect">
Inside the form, and in python:
request.form.get('multiselect').split(',')
The split is in case multiple options were selected.
BTW, that fiddle uses old versions of both vue and multiselect, but that's unrelated.

Displaying results from search API

I'm trying to get to grips with web2py/python. I want to get the user to fill in a search form, the term they search for is sent to my python script which should send the query to the blekko API and output the results to them in a new HTML page. I've implemented the following code but instead of my normal index page appearing, I'm getting the html response directly from blekko with '%(query)' /html appearing in it's search bar. Really need some help with this!
HTML form on the default/index.html page
<body>
<div id="MainArea">
<p align="center">MY SEARCH ENGINE</p>
<form name="form1" method="get" action="">
<label for="SearchBar"></label>
<div align="center">
<input name="SearchBar" type="text" id="SearchBar" value="" size = "100px"><br />
<input name="submit" type="submit" value="Search">
</div>
</form>
<p align="center"> </p>
Python code on the default.py controller
import urllib2
def index():
import urllib2
address = "http://www.blekko.com/?q='%(query)'+/html&auth=<mykey>"
query = request.vars.query
response = urllib2.urlopen(address)
html=response.read()
return html
I think you are misunderstanding how string formatting works. You need to put the address and query together still:
address = "http://www.blekko.com/?q='%(query)s'+/html&auth=<mykey>" % dict(query=request.vars.query)
Add a hidden field to your form, call it "submitted". Then reformat your controller function as such:
import urllib2
def index():
if request.vars.submitted:
address = "http://www.blekko.com/?q='%(query)'+/html&auth=<mykey>"
query = request.vars.query
response = urllib2.urlopen(address)
html=response.read()
return html
else:
return dict()
This will show your index page unless the form was submitted and the page received the "submitted" form variable.
The /html doesn't do anything. Glad your question got answered. There is python client code for the blekko search api here: https://github.com/sampsyo/python-blekko

Using Urllib instead of action in post form

I need to allow users to upload content directly to Amazon S3. This form works:
<form action="https://me.s3.amazonaws.com/" method="post" enctype='multipart/form-data' class="upload-form">{% csrf_token %}
<input type="hidden" name="key" value="videos/test.jpg">
<input type="hidden" name="AWSAccessKeyId" value="<access_key>">
<input type="hidden" name="acl" value="public-read">
<input type="hidden" name="policy" value="{{policy}}">
<input type="hidden" name="signature" value="{{signature}}">
<input type="hidden" name="Content-Type" value="image/jpeg">
<input type="submit" value="Upload" name="upload">
</form>
And in the function, I define policy and signature. However, I need to pass two variables to the form -- Content-Type and Key, which will only be known when the user presses the upload button. Thus, I need to pass these two variables to the template after the POST request but before the re-direction to Amazon.
It was suggested that I use urllib to do this. I have tried doing so the following way, but I keep getting an inscrutable HTTPError. This is what I currently have:
if request.method == 'POST':
# define the variables
urllib2.urlopen("https://me.amazonaws.com/",
urllib.urlencode([('key','videos/test3.jpg'),
('AWSAccessKeyId','<access_key'),
('acl','public-read'),
('policy',policy),
('signature',signature),
('Content-Type',content_type),
('file',file)]))
I have also tried hardcoding all the values instead of using variables but still get the same error. What am I doing incorrectly and what do I need to change to be able to redirect the form to Amazon, so the content can be uploaded directly to Amazon?
I recommend watching the form do its work with Firebug, enabled and set to the Net tab.
After completing the POST, click its [+] icon to expand, study the Headers, POST, Response tabs to see what you are missing and/or doing wrong.
Next separate this script from Django and put into a standalone file. Add one thing at a time to it and retest until it works. The lines below should increase visibility into your script.
import httplib
httplib.HTTPConnection.debuglevel = 1
I tried poking around with urllib myself, but as I don't have an account on AWS I didn't get farther than getting a 400 Bad Request response. Seems like a good sign, probably I just need valid host and key params etc.

Categories