Method not allowed for requested URL - python

I am trying to upload file from my flask site,but it keeps returning the error
method is not allowed for the requested URL. Even my teacher does not have the answer to this question. According to him he has never seen this error. really appreciate your help
my HTML file is as follows
<!DOCTYPE html>
<html lang="en">
<title> Data Collector App </title>
<head>
<link href="../static/main.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1>Data Collector</h1>
<form action={{url_for('index')}} method="POST" enctype="multipart/form-data">
<input type="file" name="file">
<button type="submit">Submit</button>
</form>
</div>
</body>
</html>
Python srcipt is
from flask import Flask, render_template, request, send_file, url_for
import pandas
from werkzeug.utils import secure_filename
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/index')
def upload():
if method == "POST":
file=request.files['file']
file.save(secure_filename("new"+file.filename))
return render_template('index.html')
if __name__ == "__main__":
app.run(debug = True)

Add any allowed methods to a route in the decorator, e.g.
#app.route('/index', methods=['POST', ...])
EDIT:
You should probably also check on the method field of request instead of just method.
if request.method == 'POST':

By default routes only accept the GET method. If you want your route to answer to other methods, pass a custom methods parameter to #app.route as follows
#app.route('/', methods=['GET', 'POST',])
...
#app.route('/index', methods=['GET', 'POST',])
...
Source https://flask.palletsprojects.com/en/1.1.x/quickstart/#http-methods

Related

get html textbox values as input to python file to print the returned value

I am trying to get value from textbox on html webpage and print it in test.py file.
There are three files:
app.py
test.py
index.html
can someone please help?
app.py:
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route("/")
def main():
return render_template("index.html")
#app.route("/", methods=["GET","POST"])
def get_provider():
dp = request.form["provider"]
dp_lower_case = dp.lower()
return dp_lower_case
if __name__ == '__main__':
app.run(debug=True)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ALMA PROCESS FLOW</title>
</head>
<body>
<form method="POST">
<label style="position:relative; left:5px; bottom:15px;"> Data Provider:</label>
<input name ="provider" type="text"">
<input type="submit" value="Generate"/>
</form>
</body>
</html>
test.py
from app import get_provider
provider = app.get_provider()
print(provider)
When you don't specify a method for a route, it defaults to a GET. This means that your code currently has 2 handlers for when your home page is loaded.
Since your form is doing a post, drop the 'GET' in the methods list i.e. change
#app.route("/", methods=["GET","POST"])
to
#app.route("/", methods=["POST"])
Better yet, you should combine everything i.e. change your code to
#app.route("/", methods=["GET","POST"])
def main():
# When it is a GET
if request.method == "GET":
return render_template("index.html")
# When it is a POST (user has submitted your form)
elif request.method == "POST":
dp = request.form["provider"]
''' Alternatively, you can use
dp = request.values.get("provider")
I prefer it because this way, I can provide a
default value in case the form parameter has no value i.e
dp = request.values.get("provider", "default provider")
'''
dp_lower_case = dp.lower()
return dp_lower_case

BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand. KeyError: 'search'

App.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="." method="post">
Search: <input type="text" name="search">
<input type="submit" value="Show">
</form>
</body>
</html>
main.py
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/CmpPr')
def cmpP():
return render_template('CmpPr.html')
#app.route('/CmpSpes')
def cmpS():
return render_template('CmpSpes.html')
#app.route('/App', methods=['POST', 'GET'])
def App():
search = request.form['search']
return render_template('output.html', n=search)
#app.route('/Gro')
def Gro():
return render_template('Gro.html')
if __name__ == '__main__':
app.run(debug=True)
I have created multiple html pages
I want to print the message, request from TextBox(above code) and print to another html page
I tried using request.form.get('search') but its returning null
And if I use request.form.get('search', FALSE or TRUE) it returns FALSE or TRUE
I have also used if else loop to specify GET and POST method, still it shows the same error
Can anyone please help me on this
Thank You
Firstly, your form action should point to the view that handle the form data (i.e. /App):
<form action="/App" method="post">
Secondly, you should only obtain the form data when the request's method is POST, since you have set method="post" in the template. Also, you will need to render the App.html that contains the form when request method is GET:
#app.route('/App', methods=['POST', 'GET'])
def App():
if request.method == 'POST': # get form data when method is POST
search = request.form['search']
return render_template('output.html', n=search)
return render_template('App.html') # when the method is GET, it will render App.html
P.S. The error you got is explained clearly that there isn't a key called search in the form data.

Executing python script with flask, from button

I'm trying to execute a def/python script from flask, when clicked on button... but can't seem to figure it out.
Here's my Python Code
from flask import Flask, redirect, url_for, render_template, request
import webbrowser
app = Flask(__name__)
#app.route("/")
def home():
return render_template("index.html")
def contact():
if "open" in request.form:
print("Test")
elif "close" in request.form:
print("Test 2")
return render_template('contact.html')
if __name__ == "__main__":
app.run(debug=True)
And here is my HTML Code
<html>
<head>
<title>Home page</title>
</head>
<body>
{% extends "base.html" %}
{% block title %}Home Page{% endblock %}
{% block content %}
<h1>Test</h1>
<input type="submit" name="open" value="Open">
<input type="submit" name="close" value="Close">
{% endblock %}
</body>
</html> ```
I don't know what is in {% block content %} but you need to have a form in order to call backend where you provide the url route that you want to call and the method you want to use (usually with forms it's POST). Also in the /contact endpoint you need to provide #app.route('/contact') and that it would accept POST request #app.route('/contact', methods=['POST']). Modify your python and HTML to look like this:
from flask import Flask, redirect, url_for, render_template, request, jsonify
import webbrowser
app = Flask(__name__)
#app.route("/")
def home():
return render_template("index.html")
#app.route('/contact', methods=['POST'])
def contact():
result = False
if "open" in request.form:
result = activate_lamp() # expecting True as a result of function
elif "close" in request.form:
result = deactivate_lamp()
return jsonify({'result': result}) # expecting True as a result of function
if __name__ == "__main__":
app.run(debug=True)
<html>
<head>
<title>Home page</title>
</head>
<body>
<h1>Test</h1>
<form action="{{ url_for('contact') }}" method="post">
<input type="submit" name="open" value="Open">
<input type="submit" name="close" value="Close">
</form>
</body>
</html>
The jsonify will return an object to the front end with default 200 response code. Then you can either do something with it or ignore it. The idea is that in the route you can call other functions, but you must return a valid HTTP response to the front-end, e.g. jsonify, or plain return '', 200 might be enough.

Flask set_cookie does not set cookie

I've been having this big issue with my python code. I'm trying to set a cookie, and sometimes the cookie gets set, but most of the time it just doesn't. I've been trying to print out the value of the cookie, and quite often (most of the time) it's None. Can anyone please help me find out what I've done wrong? I appreciate all help. Thanks in advance
This is my run.py file
from flask import Flask, request, url_for, redirect, render_template, make_response
import os
app = Flask(__name__)
app.secret_key = os.urandom(16)
#app.route('/')
#app.route('/home')
def home():
return render_template('home.html')
#app.route('/login', methods=['POST'])
def login():
user = request.form.get('username')
password = request.form.get('password')
response = make_response('')
response.set_cookie('id', 'test', domain='127.0.0.1')
return redirect('home')
if __name__ == '__main__':
app.run('127.0.0.1', debug=True)
And below here is my html code. (templates/home.html)
<html>
<head>
<title>Login Page</title>
</head>
<body>
<h1>Please login</h1>
<form method="POST" action="{{ url_for('login') }}">
<input type="text" name="username">
</br>
<input type="password" name="password">
</br>
<input type="submit">
</form>
</body>
</html>
what happens if you change your the part of your code to this
response = make_response(redirect('/home')
response.set_cookie('id', 'test')
return response

Basic flask form handling

I am trying to create a basic form in Flask that will take in the input, manipulate it and then return the output. I am running into the issue that when I am running the terminal and trying to make my app work on the http://127.0.0.1:5000/ server, the files are not visible. Not sure where the bug is?
This is how I have my files organized:
/Users/eas/Desktop/grota/templates/index.html
/Users/eas/Desktop/grota/templates/age.html
/Users/eas/Desktop/grota/app.py
This is the app.py file
from flask import Flask, render_template,request
app = Flask(__name__)
#app.route('/send',methods = ['GET','POST'])
def send():
if request.method == 'POST':
age = request.form['age']
return render_template('age.html',age=age)
return render_template('index.html')
if __name__ == '__main__':
app.run()
This is the index.html file
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
</head>
<body>
<h1>How old are you?</h1>
<form method="POST" action = "/send">
<div class = "form-group">
<input type="text" name = "age">
</div>
<input class="btn btn-primary" type="submit" value="submit">
</form>
</body>
</html>
This is the age.html file
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>Your age is{{age}}</h1>
</body>
While looking for a problem, which I try to solve I found your question. For a solution that includes full code (with py and 2 HTML files) you can see my repl.it : https://repl.it/#AlperenAtik/NaturalShortActivecell#main.py
The problems are:
In the first function, you routed your loop to "/send" page. This is why your send page did not appear. The route of the first function needs to be "/"
In the index file, the source route was shown as '/send'. Whenever I changed it to / the script worked without a problem
The other commentators already mentioned your triggering function has an indentation mistake. When host and port added appropriately, your script would work.
for ones who love the harder way- seeing things in stackoverflow- not in action, I am adding the codeblocks. Enjoy.
for main.py
from flask import Flask, render_template,request
app = Flask(__name__)
#app.route('/',methods = ['GET','POST'])
def send():
if request.method == 'POST':
age = request.form['age']
return render_template('age.html',age=age)
return render_template('index.html')
if __name__ == '__main__':
app.run(host = '0.0.0.0', port = 8080
I left the host as '0.0.0.0' and port as 8080. If you are running Python on a terminal, you may try (host = '127.0.0.1', port:5000').
for templates/index.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
</head>
<body>
<h1>How old are you?</h1>
<form method="POST" action = "/">
<div class = "form-group">
<input type="text" name = "age">
</div>
<input class="btn btn-primary" type="submit" value="submit">
</form>
</body>
</html>
for templates/age.html
<html>
<head>
</head>
<body>
<h1>Your age is {{age}}</h1>
</body>
You did not set the root route.
Or you open http://127.0.0.1:5000/send
Or you could use this quick and dirty fix (as you see in decorators now both / and /send are taken into account):
from flask import Flask, render_template,request
app = Flask(__name__)
#app.route('/',methods = ['GET'])
#app.route('/send',methods = ['GET','POST'])
def send():
if request.method == 'POST':
age = request.form['age']
return render_template('age.html',age=age)
return render_template('index.html')
if __name__ == '__main__':
app.run()
If you do not handle the '/' route nothing will happen when you open http://127.0.0.1
If you explain more clearly what is the result that you want to obtain I can help better.
Try going here: http://127.0.0.1:5000/send
If that doesn't work, what error are you getting in either your console or in your browser?
EDIT:
I just tried it, and it worked. Try reloading the page in a new tab in your browser, and see if it still occurs. This error has to do with the naming of your inputs on the webpage and the way you index your form with request.form['age']

Categories