How do I get information from a form using webapp2? - python

I have the following scenario:
<form class=*** method="post" action=("main.py" ???)>
<input class=*** type="email" name="email">
<input class=*** type="submit" value=***>
</form>
This form is in a .html file, evidently in a different file from the python code. I wish know which ways do I have to get the information from the form and send to the python file to finally work on it (I guess is something about the action field but not sure).
OBS: I must use the webapp2 (I'm using the google server so django and other stuff do not work on it)

You can see Handling Forms with webapp2 from the Google App Engine wepapp2 tutorial.
import cgi
from google.appengine.api import users
import webapp2
MAIN_PAGE_HTML = """\
<html>
<body>
<form action="/sign" method="post">
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="Sign Guestbook"></div>
</form>
</body>
</html>
"""
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.write(MAIN_PAGE_HTML)
class Guestbook(webapp2.RequestHandler):
def post(self):
self.response.write('<html><body>You wrote:<pre>')
self.response.write(cgi.escape(self.request.get('content')))
self.response.write('</pre></body></html>')
application = webapp2.WSGIApplication([
('/', MainPage),
('/sign', Guestbook),
], debug=True)
And read through the entire tutorial for more information about Datastore and template
Using template allow you to put code html code in another file.

Related

Python Tornado - Problem accessing value from Form input in HTML

I have a problem accessing the value from a Form input in HTML. I'm using Tornado.
It gives me the error: WARNING:tornado.access:404 GET /Python_Tornado_IV.py?input1=pedro (127.0.0.1) 0.00ms
These are the files:
File "Python_Tornado_IV.py":
import tornado.web
import tornado.ioloop
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render("index.html")
if self.get_argument("input1") is not None:
valor = self.get_argument("input1")
print("Valor introduzido:", valor)
else:
print("Não foi introduzido nenhum valor!")
app = tornado.web.Application([(r"/", MainHandler)])
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
File "index.html":
<!Doctype html>
<html>
<body>
<form name="form1" action="Python_Tornado_IV.py" method="get">
<input type="text" name="input1">
<input type="submit" value="Submit">
</form>
</body>
</html>
Both files are in the same directory.
In Tornado, you don't make requests to a file. Rather, you make requests to the registered urls of a handler.
As you've set the path for your MainHandler as r"/", so this is where you're supposed to make the requests to.
Change the action of your form to this:
action="/"

Passing data from HTML form through Flask to an API [duplicate]

This question already has answers here:
Get the data received in a Flask request
(23 answers)
Post values from an HTML form and access them in a Flask view
(2 answers)
Closed 3 years ago.
So I'm currently making an application in Python that would show live departures and then show a countdown when there are 0 minutes to departure. What my issue is that I don't want to edit the code to change stops, I want to just be able to input the route_type and stop from the html formand then pass that via Flask to the API.
The API is the PTV Timetable API that includes real time departures.
The API has a Swagger page so I know what to insert.
So what I've done is added the authentication code and then added the forms from bootstrap into the HTML file. I've tried googling the problem but I don't really know how the HTML forms can talk to flask so it can get added to the API.
Thanks
Python Code
def getUrl(request):
DevId = <ID>
apikey = <KEY>
request = request + ('&') if ('?' in request) else '?')
raw = 'request' +'DevId={0}'.format(DevId)
hashkey = hmac.new(key, raw, sha1)
signature = hashkey.hexdigest()
return ''https://timetableapi.ptv.vic.gov.au'+raw+'&signature={1}'.format(devId, signature)
from_zone = tz.gettz('UTC')
to_zone = tz.gettz ('Australia/Melbourne')
#get next departures
url = getUrl('/v3/departures/route_type/{route_type}/stop/{stop_id}')
#app.route('/')
#app.route('home')
def home():
return flask.render_template('home.html')
HTML Code
<body>
<form>
<div class="form-group">
<label for="station-id-input">Station ID</label>
<input type="text" class="form-control" placeholder="Station ID">
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="inline-train" value="route_type0">
<label class="form-check-label" for="inline-train">Train</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="inline-tram" value="route_type1">
<label class="form-check-label" for="inline-train">Tram</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="inline-bus" value="route_type2">
<label class="form-check-label" for="inline-train">Bus</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="inline-vline" value="route_type3">
<label class="form-check-label" for="inline-train">V/Line</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="inline-nightbus" value="route_type4" disabled>
<label class="form-check-label" for="inline-train"Night Bus (Not Implemented)</label>
</div>
</body>
So a good and well documented way to communicate with flask from html is via flask wtforms. It helps you essentially to validate your forms in the html and to secure the POST requests from the frontend usually via a CSRF token.
From the documentation you have a minimal example that could be a good starting point for you:
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import DataRequired
class MyForm(FlaskForm):
name = StringField('name', validators=[DataRequired()])
HTML
PS: The curling brackets are from jinja2, a templating language for python.
<form method="POST" action="/">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name(size=20) }}
<input type="submit" value="Go">
</form>
Validating
#app.route('/submit', methods=('GET', 'POST'))
def submit():
form = MyForm()
if form.validate_on_submit():
return redirect('/success')
return render_template('submit.html', form=form)
It is fairly straightforward, you create a form, pass it to the frontend together in the routing and then when the user submits it it tries to validate it.
With all that said, if all you want is to simply send a form data and process that in flask, all you really need to do is create / accept POST requests in your endpoint:
#app.route('/', methods=('GET', 'POST'))
#app.route('home')
def home():
if request.method == 'POST':
form = request.form
value1 = form['value1']
# do something with the values from the form.
return flask.render_template('home.html')
I would not recommend due to validation / security concerns, but it could be a starting point if you are new to flask.

Bottle: Global Variable 'request' is not defined

I am creating a web based application with python where the user enters a search query and data is returned. I used bottle to provide the web framework for this. Openshift is then used to post online. It is a simple post form and the search criteria is then used in the next section using this:
#route('/')
def search():
return '''
<h1 align="center">Twitter Sentiment Analysis</h1>
<p align="center">Enter what you would like to search in the search box below</p>
<form action="/result" method="post" align="center">
Search: <input name="search" type="text" />
<input value="Search" type="submit" />
</form>
'''
#route('/result', method='POST')
def result():
search = request.forms.get('search')
return 'it worked'
When using bottle and tested it, it worked fine, but when I try to deploy it to OpenShift, I get a name error, "global variable 'request' is not defined" when in testing it worked perfectly with just bottle before deploying to openshift, does anyone know why this may be?
It seems like you haven't imported the request or route to namespace:
from bottle import get, post, request # or route
#get('/login') # or #route('/login')
def login():
return '''
<form action="/login" method="post">
Username: <input name="username" type="text" />
...
'''
#post('/login') # or #route('/login', method='POST')
def do_login():
user = request.forms.get('username')
pass = request.forms.get('password')
...

Use POST method to delete in GAE get 405 error

Here is my code:
<form method="post" action="/del/" >
<input type="hidden" name="dealkey" value="{{deal.key()}}" />
<input class="btn btn-small" type="submit" value="Delete" />
</form>
class Delete(Handler):
def post(self):
dealid = self.request.get('dealkey')
dealid = int(dealid)
if dealid:
Book.delete(dealid)
self.redirect("/book")
app = webapp2.WSGIApplication([('/', MainPage),
('/book', BookMe),
('/del/',Delete),
],debug=True)
I am trying to use POST to delete entity in gae datastore, but i get 405, could anybody to explain it ?
How you define your Handler?
Or you can use the built-in handler and see if the error continue.
class Delete(webapp2.RequestHandler)
def post(self):
dealid = self.request.get('dealkey')
dealid = int(dealid)
if dealid:
Book.delete(dealid)
self.redirect("/book")

How to handle delete in Google App Engine (Python)

I'm a newbie programmer and new to Google App Engine and webapp2 etc. So this may be a very basic question.
I am creating an application to store images into BlobStore. My model stores description, blob_key, image url and date.
I am able to save everything, so that bit is okay.
But now I want to create a delete button which will not only delete an item from the datastore, but also delete the image saved in the blobstore.
I have created a DeleteHandler, and in the html I have a form, passing the key for the item I want to delete. In the DeleteHandler, I am using the posted key to delete the item from the datastore. I am also trying to use the key to use it delete the image saved in the blobstore.
So far I'm getting a 404 on the delete form post, and even if I get past that, I'm not sure if my DeleteHandler is correct to handle the functionality I am looking for.
Any help would be much appreciated..
Main.py:
import os
import urllib
import webapp2
from google.appengine.ext.webapp import template
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.api import images
#Models
from google.appengine.ext import db
class ImageItem(db.Model):
description = db.StringProperty(required=True)
img_url = db.StringProperty()
blob_key = blobstore.BlobReferenceProperty()
when = db.DateTimeProperty(auto_now_add=True)
#Handlers (Views)
class MainHandler(webapp2.RequestHandler):
def get(self):
upload_url = blobstore.create_upload_url('/upload')
imgs = db.GqlQuery(
'SELECT * FROM ImageItem '
'ORDER BY when DESC')
imgs_dict = {'imgs': imgs}
self.response.out.write( template.render( 'main.html',locals() ) )
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
f = self.get_uploads('file')[0] # 'file' is file upload field in the form
img =ImageItem(description=self.request.get('description'))
img.blob_key = f.key()
img.img_url = images.get_serving_url( f.key() )
img.put()
self.redirect('/')
class DeleteHandler(webapp2.RequestHandler):
def post(self):
key = self.request.get('k')
item = db.get(key)
images.delete( item.blob_key )
item.delete()
self.response.out.write(key)
#URL Routing happens here
app = webapp2.WSGIApplication([('/', MainHandler),
('/upload', UploadHandler),
('/delete', DeleteHandler)],
debug=True)
Main.html:
<form action="{{upload_url}}" method="POST" enctype="multipart/form-data">
<p>
<label for="file">Upload File</label>
<input type="file" name="file" id="file">
</p>
<p>
<label for="description">Description</label>
<input type="text" id="description" name="description">
</p>
<input type="submit" name="submit" value="Submit">
</form>
<ul>
{% for i in imgs %}
<li>
<img src="{{i.img_url}}=s400-c" alt="">
{{i.description }}
</li>
<li>{{i.when }}</li>
<li>
<form action="/delete" method="POST" enctype="multipart/form-data">
<input type="text" name="k" value="{{i.key}}" />
<input type="submit" value="delete">
</form>
</li>
{% endfor %}
</ul>
The deletes are close. Once you have a key, you can delete entities by calling db.delete(key).
For your example, this would be something like this:
class DeleteHandler(webapp2.RequestHandler):
def post(self):
key = self.request.get('k')
item = db.get(key)
blobstore.delete([item.blob_key])
db.delete(item)
self.response.out.write(key)
Your url handling in main.py is good, so it's not obvious to me why you're getting a 404. You could double-check your app.yaml file to make sure all urls are passed to main.py.
Here's a sample app.yaml handlers url section:
handlers
- url: /.*
script: main.app
Got it to work. Thanks Eric, yours was real close. I needed to use blob_key.key().
Final code is following:
class DelHandler(webapp2.RequestHandler):
def post(self):
key = self.request.get('k')
item = db.get(key)
n = item.blob_key.key()
blobstore.delete(n)
item.delete()
self.redirect('/')

Categories

Resources