Python flask form gives 405 - python

I have this form and every time I try to post it to the method in the buttom of the Question. The application just gives me a 405 error directly. I have checked that my database works by using the same method in the console.
(I have removed alot of html because it was just styling and stuff like that)
<form action="/register" method="post" class="grid">
<div class="cell colspan3" style="margin-left:2%;">
<div class="input-control modern text">
<input type="email" name="email" id="email">
<span class="label">Email</span>
<span class="informer">Skriv din email</span>
<span class="placeholder">Email</span>
</div>
</div>
<div class="cell colspan3">
<div class="input-control modern text cell">
<input type="text" name="username" id="username" >
<span class="label">Brugernavn</span>
<span class="informer">Skriv dit brugernavn</span>
<span class="placeholder">Brugernavn</span>
</div>
</div>
<div class="cell colspan3">
<div class="input-control modern text cell">
<input type="password" name="password" id="password">
<span class="label">Password</span>
<span class="informer">Skriv dit password</span>
<span class="placeholder">Password</span>
</div>
</div>
<div class="cell colspan3">
<div class="input-control modern text cell">
<input type="password" name="passwordconfirm" id="passwordconfirm">
<span class="label">Gentag password</span>
<span class="informer">Skriv dit password igen.</span>
<span class="placeholder">Gentag password</span>
</div>
</div>
<div class="cell colspan3">
<label class="input-control checkbox ">
<input type="checkbox" name="accept_tos" id="accept_tos">
<span class="check"></span>
<span class="caption">Jeg accepterer hjemmesidens regler</span>
</label>
</div>
<div class="cell colspan3">
<div class="input-control cell">
<button class="button success" type="submit">Registrer</button>
</div>
</div>
</div>
</div>
</form>
The python method that I call with my html post form:
#app.route('/register', methods=['GET', 'POST'])
def register():
form = RegistrationForm(request.form)
if request.method == 'POST' and form.validate():
newUser = User(form.username.data, form.email.data, form.password.data)
db.session.add(newUser)
db.session.commit()
return render_template('login.html')
else:
return render_template('register.html')
And the RegistrationForm method looks like this:
class RegistrationForm(Form):
username = StringField('username', [validators.Length(min=4, max=25)])
email = StringField('email', [validators.email, validators.Length(min=4, max=40)])
password = PasswordField('password',
[validators.Required(),
validators.EqualTo('confirm', message='Passwords skal matche hinanden.')
])
confirm = PasswordField('passwordconfirm')
accept_tos = BooleanField('Jeg accepterer regler for denne hjemmeside', [validators.Required()])

obviously there'snt any problem in these codes unless you have url_prefix for your current app like :
app = Blueprint('user', __name__, url_prefix='/user/')
and u have another blueprint with url_prefix like :
app = Blueprint('general', __name__, url_prefix='/')
with another funtion like :
#app.route('/register', methods=['GET'])
in the blueprint ...
and your form is posting data to '/register' instead of '/user/register'

If that really is the code you're using, I can't see why you're getting a 405 Unsupported Method rather than a validation error. You need to render the hidden CSRF field in the html form.
<form ...>
{{ form.hidden_tag() }}
There are other things wrong with this code. Redirect to login, don't render the template from the register view. Use form.validate_on_submit(). Don't pass request.form to the form. Let the form render the inputs, don't write the html yourself.

Try changing
if request.method == 'POST' and form.validate():
to
if form.validate_on_submit():

Related

Is there anyway to know at which card "add comment" has clicked using flask

I'm trying to add a comment section to my web app however, I want to know which book its "add comment" has clicked I'm thinking about getting the book's ID.
Here is my python
#app.route("/comment", methods=["GET", "POST"])
def comment():
if request.method == "POST":
if not request.form.get("comment"):
return apology("must provide comment", 400)
book = request.form.get("book_id")
print(session["user_id"])
print(book)
id = session["user_id"]
print(id)
user = db.execute("SELECT username FROM users WHERE id=?", id)
db.execute("INSERT INTO comment (comment, user,book_id) VALUES(?, ?,?)", comment, user,book)
return render_template ("index.html")
else:
return render_template ("comment.html")
Here is my html code
<form action="/comment" method="get">
<div class="container">
<div class="row g-3">
{% for book in books %}
<div class="col-12 col-md-6 col-lg-4">
<div class="card">
<img src="{{book.volumeInfo.imageLinks.smallThumbnail}}">
<div class="card-body">
<h5 style="color:red" class="card-title">{{book.volumeInfo.title}}</h5>
<p style="color:blue" class="card-text">{{book.volumeInfo.authors}}</p>
<p style="visibility:hidden" class="card-text">{{book.id}}</p>
<input name="book" style="visibility:hidden" class="form-control mx-auto w-auto" name="book_id" value="{{book.id}}" type="text">
More Info
<button value="{{book.id}}" class="btn btn-primary">add comment</button>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
This HTML element
<input name="book" style="visibility:hidden" class="form-control mx-auto w-auto" name="book_id" value="{{book.id}}" type="text">
has two different values for attribute name, please try removing one of them, that is
<input name="book_id" style="visibility:hidden" class="form-control mx-auto w-auto" value="{{book.id}}" type="text">
and then write if you can access book_id properly in your Flask application. As side if you need to have input invisble to user you might use type="hidden" rather than tinker with styling, in this case
<input name="book_id" value="{{book.id}}" type="hidden">

Trouble linking HTML login code with apps.py Python code with Flask

I have this code which runs in the navbar, it's meant to implement a login/registration form but without leaving the home page, its a toggler with a data-target="#login-form":
<i class="icon-user"></i> Sign In
How do I change the #app.route so that it targets the login-form that's implemented within the home page? Python code used:
#app.route('/')
def home():
# Check if user is loggedin
if 'loggedin' in session:
# User is loggedin show them the home page
return render_template('home.html', username=session['username'])
# User is not loggedin redirect to login page
return redirect(url_for('home'))
#app.route('/login/', methods=['GET', 'POST'])
def login():
cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
# Check if "username" and "password" POST requests exist (user submitted form)
if request.method == 'POST' and 'username' in request.form and 'password' in request.form:
username = request.form['username']
password = request.form['password']
print(password)
# Check if account exists using MySQL
cursor.execute('SELECT * FROM users WHERE username = %s', (username,))
# Fetch one record and return result
account = cursor.fetchone()
if account:
password_rs = account['password']
print(password_rs)
# If account exists in users table in out database
if check_password_hash(password_rs, password):
# Create session data, we can access this data in other routes
session['loggedin'] = True
session['id'] = account['id']
session['username'] = account['username']
# Redirect to home page
return redirect(url_for('home'))
else:
# Account doesnt exist or username/password incorrect
flash('Incorrect username/password')
else:
# Account doesnt exist or username/password incorrect
flash('Incorrect username/password')
return render_template('home.html')
<div class="modal fade c-content-login-form" id="login-form" role="dialog">
<div class="modal-dialog">
<div class="modal-content c-square">
<div class="modal-header c-no-border">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<h3 class="c-font-24 c-font-sbold">Good Afternoon!</h3>
<p>Let's make today a great day!</p>
<form>
<div class="form-group" method="post">
<label for="username" class="hide">Username</label>
<input type="username" class="form-control input-lg c-square" name="username" id="username" placeholder="Username">
</div>
<div class="form-group">
<label for="password" class="hide">Password</label>
<input type="password" class="form-control input-lg c-square" name="password" id="password" placeholder="Password">
</div>
<div class="form-group">
<div class="c-checkbox">
<input type="checkbox" id="login-rememberme" class="c-check">
<label for="login-rememberme" class="c-font-thin c-font-17">
<span></span>
<span class="check"></span>
<span class="box"></span>
Remember Me
</label>
</div>
</div>
<div class="form-group">
<input type="submit" value="Login" class="form-control btn btn-success btn c-theme-btn btn-md c-btn-uppercase c-btn-bold c-btn-square c-btn-login" name="">Login</input>
Forgot Your Password ?
</div>
<div class="clearfix">
<div class="c-content-divider c-divider-sm c-icon-bg c-bg-grey c-margin-b-20">
<span>or signup with</span>
</div>
<ul class="c-content-list-adjusted">
<li>
<a class="btn btn-block c-btn-square btn-social btn-twitter">
<i class="fa fa-twitter"></i>
Twitter
</a>
</li>
<li>
<a class="btn btn-block c-btn-square btn-social btn-facebook">
<i class="fa fa-facebook"></i>
Facebook
</a>
</li>
<li>
<a class="btn btn-block c-btn-square btn-social btn-google">
<i class="fa fa-google"></i>
Google
</a>
</li>
</ul>
</div>
</form>
I understand linking specific pages but what if it isn't exactly a page you want to link
You already have the navbar and the modal form there. Now you need some javascript that makes the link toggle the modal box visibility.
And also some javascript that intercepts the form submission, prevents it from loading another page, grabs the form data, and posts it to the flask endpoint. Please lookup javascript fetch() post data.
Edit: please check Matiiss comment below. It seems Bootstrap already provides the js code you need.
This is my approach to have a login forma and home page on the same route (could probably use two templates but this works too):
The main file:
from flask import Flask, redirect, url_for, request, render_template
from wtforms import StringField, SubmitField
from wtforms.validators import InputRequired
from flask_wtf import FlaskForm
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_key_'
user_logged_in = False
class LoginForm(FlaskForm):
username = StringField('Username', validators=[InputRequired()])
password = StringField('Password', validators=[InputRequired()])
submit = SubmitField('Login')
#app.route('/', methods=['GET', 'POST'])
def home():
global user_logged_in
if user_logged_in:
return render_template('home.html', logged_in=user_logged_in)
else:
form = LoginForm()
if form.validate_on_submit():
user_logged_in = True
return redirect(url_for('home'))
return render_template('home.html', logged_in=user_logged_in, form=form)
if __name__ == '__main__':
app.run(debug=True)
Obviously you need to use your user login validation, this is just to for testing (logged_in variable)
(Also I spent like 20 min trying to figure out why I couldn't submit form and it was because I didn't include {{ form.hidden_tag() }} in my form)
The template (super simple):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
{% if logged_in %}
<h1>You are logged in</h1>
<p>{{ logged_in }}</p>
{% else %}
<form action="{{ url_for('home') }}" method="POST">
{{ form.hidden_tag() }}
<div>
{{ form.username.label }}
{{ form.username }}
</div>
<div>
{{ form.password.label }}
{{ form.password }}
</div>
{{ form.submit }}
</form>
<p>{{ logged_in }}</p>
{% endif %}
</body>
</html>
Basically You check if user is logged in and then just simply pass that variable to the template and there is a huge if statement, I should tho point out that using a modal in this case is not the best idea, you have to just show completely only the login part otherwise someone may open DevTools and just delete that modal and gain accesss to the home page
If You have any questions, ask

How to get HTML Input using Python Flask

I am planning to get input from an HTML Form when submitted, the input will be send over to Python. Here is the HTML File
<form method="GET">
<div class="form-inline">
<div class="form-group">
<input type="email" class="line-input" name="userEmail" placeholder="Email">
</div>
<div class="form-group">
<input type="password" class="line-input" name="userPassword" placeholder="Password">
</div>
</div>
<div class="form-inline">
<div class="form-group">
<input type="email" class="line-input" name="recipientMail" placeholder="Recipient">
</div>
<div class="form-group">
<input type="email" class="line-input" name="CCEmail" placeholder="CC">
</div>
</div>
<div class=" form-group">
<button type="submit" class="btn btn-light text-primary btn-block" style="margin : 20px 20px -10px 0px">Send Message</button>
</div>
</form>
Now I don't know the best way to do this, I tried this in Python but doesn't seem to work
#app.route('/', methods=['POST'])
def form_post():
userEmail = request.form['userEmail']
userPassword = request.form['userPassword']
return userEmail, userPassword
Can anyone help me out here?
Change your form method from GET to POST, as your route only specifies "POST", and will not accept any other requests of a different type:
<form method="POST">
Edit: if you wish to specify both methods, ensure that your route checks for the correct type of request currently being sent when the route is triggered:
#app.route('/', methods=['POST','GET'])
def form_post():
if flask.request.method == 'POST'
userEmail = request.form['userEmail']
userPassword = request.form['userPassword']
return userEmail, userPassword
return flask.render_template('something.html')
Note, however, that you are creating your form on the home route ('/'). It may be best to return a link to the page that has the form code:
#app.route('/')
def home():
return 'Welcome! login here'
#app.route('/login', methods=['GET', 'POST']):
if flask.request.method == 'POST'
userEmail = request.form['userEmail']
userPassword = request.form['userPassword']
return flask.redirect('/')
return flask.render_template('form_filename.html')

Python Flask bad request

I'm making a text based browser game in python and flask but I encountered a strange problem.
When I try to login on my website I get a "bad request" error.
This is my login route:
#app.route('/login/', methods=['GET','POST'])
def login():
if current_user.is_authenticated:
return redirect("/game/", code=302)
# when the form is filled in
if request.method == 'POST':
# register the user
if request.form['regSubmit'] == 'regSubmit':
username = request.form['regUser']
password = request.form['regPassword']
address = request.form['regAddress']
register_user(username=username,password=password,address=address)
print(address)
return redirect("/login/", code=302)
# login user
if request.form['logSubmit'] == 'logSubmit':
print('lol')
username = request.form['logUser']
password = request.form['logPassword']
result = users.find_one({"user": username})
if result and check_password_hash(result['password'], password):
user_obj = User(result['_id'])
login_user(user_obj)
return redirect("/game/", code=302)
return render_template('out.html')
This is my login modal:
<div id="loginModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Login</h4>
</div>
<form method="post">
<div class="modal-body">
<p>Please enter your username and password.</p>
<div class="form-group">
<label class="control-label" for="logUser">Username</label>
<input type="text" name="logUser" class="form-control" id="logUser">
</div>
<div class="form-group">
<label class="control-label" for="logPassword">Password</label>
<input type="password" name="logPassword" class="form-control" id="logPassword">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" name="logSubmit" value="logSubmit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
</div>
I believe your code is failing because you're trying to access request.form['regSubmit'], but this field does not exist in your form. Accessing any form fields that do not exist will cause Flask to return a 400 Bad Request error.
To get around this, you can either submit your login and register actions to different Flask views, or you can use a try...except block to catch the KeyError generated by trying to access a non-existent form field.

How to write python script in flask

I have problem about my python script with HTML.
I'm newbie.
My python script looks as follow:
#!/usr/bin/python3.4
# Import modules for CGI handling
import cgi, cgitb
# Create instance of FieldStorage
form = cgi.FieldStorage()
# Get data from fields
first_name = form.getvalue('first_name')
last_name = form.getvalue('last_name')
print("Content-type:text/html\r\n\r\n")
print("<html>")
print("<head>")
print("<title>Hello - Second CGI Program</title>")
print("</head>")
print("<body>")
print("<h2>Hello %s %s</h2>" % (first_name, last_name))
print("</body>")
print("</html>")
and my HTML file:
<form action="hello_get.py" method="get">
First Name: <input type="text" name="first_name"> <br />
Last Name: <input type="text" name="last_name" />
<input type="submit" value="Submit" />
</form>
I run HTML and write to input first name and last name, but my script doesn't start. It's just show the windows If I want to open script, or save it.
EDIT:
My HTML:
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
<p>Want to get in touch with me? Fill out the form below to send me a message and I will try to get back to you within 24 hours!</p>
<!-- Contact Form - Enter your email address on line 19 of the mail/contact_me.php file to make this form work. -->
<!-- WARNING: Some web hosts do not allow emails to be sent through forms to common mail hosts like Gmail or Yahoo. It's recommended that you use a private domain email address! -->
<!-- NOTE: To use the contact form, your site must be on a live web host with PHP! The form will not work locally! -->
<form action="/app/get.cgi" method="get">
<div class="row control-group">
<div class="form-group col-xs-12 floating-label-form-group controls">
<label>Name</label>
<input type="text" name="name" class="form-control" placeholder="Name" id="name" required data-validation-required-message="Please enter your name.">
<p class="help-block text-danger"></p>
</div>
</div>
<div class="row control-group">
<div class="form-group col-xs-12 floating-label-form-group controls">
<label>Email Address</label>
<input type="email" name="email" class="form-control" placeholder="Email Address" id="email" required data-validation-required-message="Please enter your email address.">
<p class="help-block text-danger"></p>
</div>
</div>
<div class="row control-group">
<div class="form-group col-xs-12 floating-label-form-group controls">
<label>Message</label>
<textarea rows="5" name="message" class="form-control" placeholder="Message" id="message" required data-validation-required-message="Please enter a message."></textarea>
<p class="help-block text-danger"></p>
</div>
</div>
<br>
<div id="success"></div>
<div class="row">
<div class="form-group col-xs-12">
<button type="submit" class="btn btn-default">Odoslať</button>
</div>
</div>
</form>
</div>
</div>
</div>
(my python script) get.cgi:
#!/usr/bin/python3.4
# Import modules for CGI handling
import cgi, cgitb
file = open('file.txt', mode='w')
form = cgi.FieldStorage()
name = form.getvalue('name')
email = form.getvalue('email')
message = form.getvalue('message')
file.write(name)
file.write(email)
file.write(message)
file.close()
and my app.py which is main flask module
from flask import Flask, render_template, request
app = Flask(__name__)
app.secret_key = 'mypa$$w0rd'
#app.route('/')
#app.route('/index.html')
def index():
return render_template('index.html')
#app.route('/about.html')
def about():
return render_template('about.html')
#app.route('/contact.html')
def contact():
return render_template('contact.html')
#app.route('/post.html')
def sample_post():
return render_template('post.html')
if __name__ == '__main__':
app.run()
I'm running it as localhost.
Output when i click on SEND(in my html it equals ODOSLAT in my language):
Not Found
The requested URL was not found on the server. If you entered the URL
manually please check your spelling and try again.
And text field in browser search now looks like this:
http://127.0.0.1:5000/app/get.cgi?name=asdf&email=julo.marko%40gmail.com&message=asfasfasf
If you have a Flask web application, you don't need any .cgi scripts. Just point your form to the appropriate route in flask. With the url in your html:
#app.route('/api/get.cgi')
def api_get():
first_name = request.args.get('first_name')
last_name = request.args.get('last_name')
return """<html><body><h2>Hello %s %s</h2></body></html>""" % (first_name, last_name)

Categories