Hey im making a program in flask that lets users fill out a form and then it will email that form to a specific email. It was working perfectly fine before but for some reason now it is not. Here is my code:
#app.route('/application', methods=['POST', 'GET'])
def application():
if request.method == 'POST':
name = request.form["name"]
github = request.form["github"]
age = request.form["age"]
location = request.form["location"]
email = request.form["email"]
discord = request.form["discord"]
return redirect(f"/final/{name}/{github}/{age}/{location}/{email}/{discord}/")
#app.route('/final/<name>/<github>/<age>/<location>/<email>/<discord>/', methods=['GET','POST'])
def final(name, github, age, location, email, discord):
mail= Mail(app)
app.config['MAIL_SERVER']='smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USERNAME'] = 'prodatacollectors#gmail.com'
app.config['MAIL_PASSWORD'] = '*******'
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USE_SSL'] = True
b = Markup(f"Name: {name}\r\nGithub: {github}\r\nAge: {age}\r\nlocation: {location}\r\nemail: {email}\r\ndiscord: {discord}")
msg = Message(f'Application {name}', sender = 'prodatacollectors#gmail.com', recipients = [email])
msg.body = b
mail.send(msg)
return render_template("final.html" )
HTML TEMPLATE
<form action="/application" method="POST">
<p><input type = "text" name="name" placeholder="First And Last Name" /></p>
<br><br>
<p><input type = "text" name="github" placeholder="GitHub Profile Link" /></p>
<br><br>
<p><input type = "text" name="age" placeholder="Age" /></p>
<br><br>
<p><input type = "text" name="location" placeholder="State/Country" /></p>
<br><br>
<p><input type = "text" name="email" placeholder="Email" /></p>
<br><br>
<p><input type = "text" name="discord" placeholder="Discord username and tag(if you have one)" /></p>
<p><input type="submit" value="Submit" /></p>
</form>
I get no errors all it says is that the the requested url wasnt found on the server
So i found an answer. So flask doesnt allow specifc links such as https://github.com/codingdudepy to be returned as a redirect url. Nor does it allow things like #, or domains like .com for some reason. When i removed these things it worked perfectly.
Related
I have made a form and set method=post and while taking request.post['name'] to a variable MultiValueDictKeyError is Coming why is that ?
<form action="verify_user" method="post">
{% csrf_token %}
<input required type="text" placeholder="Name" name="name"><br><br>
<input required type="password" placeholder="Password" name="password"><br><br>
<input required type="passord" placeholder="Confirm password" name="confirm_password" id=""> <br><br>
<br><br><h1>{{ messages }}</h1>
<button type="submit">Create</button>
</form>
this is my form ------
def verify_user(request):
inputname = request.POST['name']
inputpass = request.POST['password']
inputconfirmpass = request.POST['confirm_password']
if not inputpass == inputconfirmpass:
messages.info(request,"Passwords don't match")
else:
messages.info(request,"Passwords match")
return redirect('/verify_user')
this is my function in views.py -------------
MultiValueDictKeyError at /verify_user
'name'
Request Method: GET
Request URL: http://127.0.0.1:8000/verify_user
Django Version: 4.1.2
Exception Type: MultiValueDictKeyError
Exception Value: 'name'
this is the error --------
Try to provide another name as name for e.g. person_name something like that, also I'd recommend you to use .get() so that you can also provide some other default value.
views.py:
def verify_user(request):
if request.method=="POST":
inputname = request.POST.get('person_name', False)
inputpass = request.POST.get('password', False)
inputconfirmpass = request.POST.get('confirm_password', False)
if not inputpass == inputconfirmpass:
messages.info(request,"Passwords don't match")
else:
messages.info(request,"Passwords match")
return redirect('/verify_user')
else: # GET request
return render(request, "some_folder_name/your_template.html")
Template file:
<form method="POST">
{% csrf_token %}
<input required type="text" placeholder="Name" name="person_name"><br><br>
<input required type="password" placeholder="Password" name="password"><br><br>
<input required type="passord" placeholder="Confirm password" name="confirm_password" id=""> <br><br>
<br><br><h1>{{ messages }}</h1>
<button type="submit">Create</button>
</form>
I have two forms:
auth.html
<form class="form-signin pt-5" action="/auth/" method="post" >
{% if error_msg: %}
{{ error_msg }}
{% endif %}
<div class="mt-5 form-label-group">
<p class="text-muted">email</p>
<input type="email" id="inputEmail" class="form-control" name = "email" required autofocus>
</div>
<div class="form-label-group">
<p class="text-muted"> password</p>
<input type="password" id="inputPassword" name="password" class="form-control" required>
<label for="inputPassword"></label>
</div>
<div class="checkbox mb-3"></div>
<button class="btn btn-lg btn-danger btn-block" type="submit">Enter</button>
</form>
success form.html
Success
code in flask is:
app = Flask(__name__)
app.secret_key = "randomstring"
app.config["SECRET_KEY"] = "secret_key"
app.config["EMAIL"] = "test#test.ru"
app.config["PASSWORD"] = "test"
#app.route("/auth/", methods=["GET", "POST"])
def auth_open():
error_msg = "" # Пока ошибок нет
if request.method == "POST":
email = request.form.get("username")
password = request.form.get("password")
if ((email and password) and email == app.config["EMAIL"] and password == app.config["PASSWORD"]):
session["is_auth"] = True
return render_template("/")
else:
error_msg = "Error login or password"
return render_template("auth.html", error_msg=error_msg)
When I input password and login it shows me error message instead of success form.How should I solve this problem?
email = request.form.get("email")
I have coded the below form and controller but when the page is loaded, the page automatically send request to my database. How to change the form or controller and just send request when I clicked create button.
html code:
<form method="POST" action="/conference/create">
<div class="field">
<div class="control">
<input class="input is-large" type="text" name="name" placeholder="Your Name" autofocus="">
</div>
</div>
<input class="input is-large" type="text" name="shortname" placeholder="Your Shortname">
</div>
</div>
<div class="field">
<div class="control">
<input class="input is-large" type="text" name="year" placeholder="Year">
</div>
</div>
<button class="button is-block is-info is-large is-fullwidth">Create</button>
</form>
</div>
</div>
{% endblock %}
controller function:
#main.route('/conference/create', methods=['POST','GET'])
#login_required
def create_conference():
name = request.form.get('name')
shortname = request.form.get('shortname')
year = request.form.get('year')
startdate = request.form.get('startdate')
enddate = request.form.get('enddate')
submissiondeadline = request.form.get('submissiondeadline')
website = request.form.get('website')
tag = request.form.get('tag')
datem = datetime.today().replace(day=1)
conference = Conference(confid="1", creationdatetime=datem, name=name, shortname=shortname, year=year, startdate=startdate,
enddate=enddate, submissiondeadline=submissiondeadline, creatoruser=12, website=website)
conferenceTag = ConferenceTags("1", tag)
db.session.add(conference)
db.session.commit()
db.session.add(conferenceTag)
db.session.commit()
return render_template('create_conference.html')
By the way, I have changed controller's method parameters with just 'POST' when I do that it gives me not allowed methods error.
you should add an if statement to specify if the incoming request is POST or GET and act accordingly.
if request.method=='GET':
#load page
elif request.method=='POST':
#update database
#main.route('/conference/create', methods=['POST','GET'])
#login_required
def create_conference():
if request.method == 'POST':
name = request.form.get('name')
shortname = request.form.get('shortname')
year = request.form.get('year')
startdate = request.form.get('startdate')
enddate = request.form.get('enddate')
submissiondeadline = request.form.get('submissiondeadline')
website = request.form.get('website')
tag = request.form.get('tag')
datem = datetime.today().replace(day=1)
conference = Conference(confid="1", creationdatetime=datem, name=name, shortname=shortname, year=year, startdate=startdate,
enddate=enddate, submissiondeadline=submissiondeadline, creatoruser=12, website=website)
conferenceTag = ConferenceTags("1", tag)
db.session.add(conference)
db.session.commit()
db.session.add(conferenceTag)
db.session.commit()
return 'you want to do.'
return render_template('create_conference.html')
Python Side Routing
#app.route("/loginC", methods=["POST"])
def loginPage():
valid = request.form["idnumber"]
if valid is not None: #Creating A New User
username = request.form["username"]
password = request.form["password"]
firstname = request.form["firstname"]
lastname = request.form["lastname"]
idnumber = request.form["idnumber"]
logins["'"+username+"'"] = {"password":"'"+ password +"'", "firstname":"'"+ firstname +"'", "lastname":"'"+ lastname +"'", "idnumber":"'"+ idnumber +"'"}
session["currentUser"] = username
isLogin = True
return redirect("/login")
else:
username = request.form["username"]
password = request.form["password"]
for account in logins:
if username == logins:
if logins["'"+username+"'"]["password"] == password:
session["currentUser"] = username
isLogin = True
return redirect("/login")
return redirect("/login")
Html
<form action="/loginC" class="formLogin" method="post">
<h3>Existing User</h3>
Username: <input type="text" name="username" placeholder="username" required><br>
Password: <input type="password" name="password" placeholder="password" required><br>
<input type="submit" value="Login">
</form>
<br>
<hr class="formLogin">
<br>
<form action="/loginC" class="formLogin" method="post">
<h3>New User</h3>
Username: <input type="text" name="username" placeholder="username" required><br>
Password: <input type="password" name="password" placeholder="password" required> <br>
Firstname: <input type="text" name="firstname" placeholder="firstname" required><br>
Lastname: <input type="text" name="lastname" placeholder="lastname" required><br>
Student ID: <input name="idnumber" type="text" placeholder="ID number" required><br>
<input type="submit" value="Create">
</form>
I keep getting the error:
"werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'idnumber'"
it is requesting the form in the second for bracket aka the 'new user' bracket
In place of :
valid = request.form["idnumber"]
Change to :
If you want to retrieve POST data:
valid = request.form.get("idnumber")
If you want to retrieve GET (query string) data:
valid = request.args.get("idnumber")
Also :
Change method to
#app.route("/loginC", methods=["GET", "POST"])
I am getting Invalid captcha response for below set up. Contact form worked perfectly fine, I added rule that verifies captcha, I checked secret keys and still getting Invalid Captcha even after solving it. Below is my setup:
views.py
def get_client_ip(request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = request.META.get('REMOTE_ADDR')
return ip
def grecaptcha_verify(request):
response = {}
data = request.POST
captcha_rs = data.get('g-recaptcha-response')
url = "https://www.google.com/recaptcha/api/siteverify"
params = {
'secret': settings.RECAPTCHA_SECRET_KEY,
'response': captcha_rs,
'remoteip': get_client_ip(request)
}
verify_rs = requests.get(url, params=params, verify=True)
verify_rs = verify_rs.json()
response["status"] = verify_rs.get("success", False)
response['message'] = verify_rs.get('error-codes', None) or "Unspecified error."
return response
def contact(request):
if request.method == 'POST':
if grecaptcha_verify(request) == "success":
subject = request.POST.get('subject')
message = request.POST.get('message')
email = request.POST.get('email')
if subject and message and email:
try:
send_mail(subject, message, email, ['myemail#gmail.com'],fail_silently= True)
except BadHeaderError:
return HttpResponse('{Bad Header}')
return greatsuccess(request)
else:
return HttpResponse('{Invalid Form}')
else:
return HttpResponse('Invalid Captcha')
return render(request, 'personal/contact.html')
My template:
<div class="form-area">
<form role="form" method="POST">
{% csrf_token %}
<input type="text" class="form-control" id="subject" name="subject" placeholder="Subject" maxlength="70" required>
</div>
<br>
<div class="form-group">
<input type="email" class="form-control" id="email" name="email" placeholder="Email" required>
</div>
<div class="form-group">
<textarea class="form-control" type="textarea" id="message" name="message" placeholder="Message" maxlength="300" rows="7"></textarea>
</div>
<button type="submit" name="submit" class="btn btn-m btn-secondary">Submit</button>
<script src='https://www.google.com/recaptcha/api.js'></script>
<div class="g-recaptcha" data-sitekey="MYKEY"></div>
</form>
I am quite new to Python, how to check what is happening in the background and at which point verification fails?
You are making get request for verification, but you need to make post request to it. That is why captcha verification failing. So try like this:
url = "https://www.google.com/recaptcha/api/siteverify"
headers = {'User-Agent': 'DebuguearApi-Browser',}
params = {'secret': settings.RECAPTCHA_SECRET_KEY, 'response': captcha_rs}
verify_rs = requests.post(url, data=params, headers=headers) # <-- Update Here
... # rest of your code
Please see the documentation on how to verify recaptcha.
Ok.
I got it working. Thanks Ruddra for all the help.
I deleted first </div> as I've noticed this was unnecessary. This allowed g-recaptcha-response to be included in POST data. Apparently it's important to make sure your form is correct and google likes it.
Secondly I did some modifications to main views.py as per advice I received+ some improvements.
def greatsuccess(request):
messages.success(request, "Email sent!")
return render(request, 'personal/contact.html')
def greatfail(request):
messages.error(request, "Invalid Captcha!")
return render(request, 'personal/contact.html')
def grecaptcha_verify(request):
data = request.POST
captcha_rs = data.get('g-recaptcha-response')
url = "https://www.google.com/recaptcha/api/siteverify"
headers = {'User-Agent': 'DebuguearApi-Browser',}
params = {'secret': settings.RECAPTCHA_SECRET_KEY, 'response': captcha_rs}
verify_rs = requests.post(url,params, headers=headers)
verify_rs = verify_rs.json()
response = verify_rs.get("success", False)
return response
def contact(request):
if request.method == 'POST':
response=grecaptcha_verify(request)
if response == True :
subject = request.POST.get('subject')
message = request.POST.get('message')
email = request.POST.get('email')
if subject and message and email:
try:
send_mail('Sent from mywebsite '+subject, message, email, ['email#gmail.com'],fail_silently= True)
except BadHeaderError:
return HttpResponse('{Bad Header}')
return greatsuccess(request)
else:
return HttpResponse('{Invalid Form}')
else:
greatfail(request)
return render(request, 'personal/contact.html')
My template:
<form method="POST">
{% csrf_token %}
<input type="text" class="form-control" id="subject" name="subject" placeholder="Subject" maxlength="70" required>
<br>
<div class="form-group">
<input type="email" class="form-control" id="email" name="email" placeholder="Email" required>
</div>
<div class="form-group">
<textarea class="form-control" type="textarea" id="message" name="message" placeholder="Message" maxlength="300" rows="7"></textarea>
</div>
<div class="g-recaptcha" data-sitekey="key"></div>
<button type="submit" name="submit" class="btn btn-m btn-secondary">Submit</button>
</form>
{% for message in messages %}
{{ message }}
{% endfor %}