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')
...
Related
I have a rather silly question.
I am trying an app and have two forms on it:
Enter a zip code (submit button)
or
Login if you already have a user id. (submit button)
Now in my code (python using web.py framework) i have two def POST(self) but which one will the first form and the second login form call?
I am super confused. Now my friend tells me html cannot have two different forms.
Here is the code and the form is incomplete - i am just trying to get the methods running well before I start grabbing more data and building a db schema.
import web
from web import form
render = web.template.render('templates/')
urls = (
'/', 'index'
)
myform = form.Form(
form.Textbox("Zip Code",
form.regexp('^\d{5}$', 'Not a zip code'),
description='Enter a 5 digit zip code',
maxlength = '5'),
)
myloginform = form.Form(
form.Textbox("Username",
form.regexp('^[^<>\s\#]+(\#[^<>\s\#]+(\.[^<>\s\#]+)+)$', 'Invalid username'),
description='Enter your username'),
)
class index:
def __init__(self): ** i still dont know wtf this does..
pass
def GET(self):
form = myform()
myloginform1 = myloginform()
return render.index(form,myloginform1)
def POST(self):
form = myform()
if not form.validates():
return render.index(form)
else:
return "The zip code you are located is: %s" % (form['Zip Code'].value)
def POST(self):
myloginform1 = myloginform()
if not myloginform1.validates():
return render.index(myloginform1)
else:
return "Welcome %s" % (myloginform1['Username'].value)
class testfunc:
def GET(self):
return "Test function returning!"
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
The index.html is below
$def with (form, myloginform1)
<html>
<head><title>8reps Welcome.. </title></head>
<body>
<h3>Hi</h3>
<p> Lets find some results in your area.. </p>
<form name="main" method="post">
$if not form.valid: <p class="error">Try again...</p>
$:form.render()
<input type="submit" /> </form>
<p> Already registered? Login as a user..</p>
<form name="login" method="post">
$if not myloginform1.valid: <p class="error">Try again..</p>
$:myloginform1.render()
<input type="submit" />Login</form>
</form>
</body>
</html>
Thank you!!
you may have as many forms on the page as you want, the only issue is how you will handle them.
there are 2 options:
two separate backends e.g. /login and /zip to handle POSTs from forms - in the form tag you will need to add action attribute to direct POSTs properly
single /index where you can handle both forms, but then you need to recognize which form was posted, e.g. by presence of some named field (you can use submit input with the same name but different values:
<input name="submit" type="submit" value="Zip" />
and for the second form:
<input name="submit" type="submit" value="Login" />
then you will know which form was posted by checking value of sent "submit" field.
for sure, you can't have 2 methods wit the same name in class definition.
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.
Ok I have checked some of the related questions and can't seem to find the exact one.
Basically I have pretty much hard-coded a website, there's a tiny bit of use of bootstrap.
I wanted to code a contact form, I've started to learn Python and therefore used Flask to code one.
Right now the form is separate to all of the html files because I coded a separate project.
I know that I could create a full Flask project and redefine all of my html files through the app and have the app generate URL's for it, but that would be a hell of a lot of work at this point for the sake of a contact form.
Is there any way that I can define the form in HTML and have it refer to the Python Flask script?
I have literally no idea how to do this and I can't find an answer anywhere on Google but then I might be searching the wrong thing.
So, here's my HTML:
<form action="routes.py" method="post" class="basic-grey">
<label>
<span>Your Name :</span>
<input id="name" type="text" name="name" placeholder="Your Full Name" />
</label>
<label>
<span>Your Email :</span>
<input id="email" type="email" name="email" placeholder="Valid Email Address" />
</label>
<label>
<span>Message :</span>
<textarea id="message" name="message" placeholder="Your Message to Us"></textarea>
</label>
<label>
<span> </span>
<input type="button" class="button" value="Send" />
</label>
</form>
And here is the Python Flask Script:
# Imported the Flask class and a function render_template
from flask import Flask, render_template, request, flash
from forms import ContactForm
from flask.ext.mail import Message, Mail
import os
mail = Mail()
# Created an instance/object of the Flask class
app = Flask(__name__)
app.secret_key = os.urandom(24)
# Mapped the URL '/' to the function home().
# Now when someone visits this URL, the function home() will execute.
# This uses a decorator to tell Flask which URL will cause the function below it to execute.
app.config['MAIL_SERVER']='smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USERNAME'] = 'fernindustrials#gmail.com'
app.config['MAIL_PASSWORD'] = 'l3d23pp3l1n'
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USE_SSL'] = True
mail.init_app(app)
#app.route('/contact', methods=['GET','POST'])
def contact():
form = ContactForm()
if request.method == 'POST':
if form.validate() == False:
flash('All fields are required.')
return render_template('contact.html', form=form)
else:
msg = Message(form.subject.data, sender='contact#example.com')
msg.recipients = ["fernindustrials#gmail.com"]
msg.body="""
From: %s <%s>
%s
""" % (form.name.data, form.email.data, form.message.data)
mail.send(msg)
return render_template('posted.html')
elif request.method == 'GET':
return render_template('contact.html', form=form)
# Use run() to run our app on a local server.
if __name__ == '__main__':
app.run(debug = True)
In order to not breach the rules I wont post the Forms.py file that I have unless someone needs that to.
Is there anything I need to change or do differently?
Is it even possible?
Also where does the script go in reference to the index.html files, i.e what is the project structure?
The action field in your form tag should be set to an endpoint, not a script. This is unlike PHP, where you do specify the script.
So your form tag may look like:
<form action="/contact" method="POST" class="basic-grey">
I am using a flask framework, and can't seem to delete rows from the database. The code below gives a 405 error: "The method is not allowed for the requested URL." Any ideas?
In the py:
#app.route('/delete/<postID>', methods=['POST'])
def delete_entry():
if not session.get('logged_in'):
abort(401)
g.db.execute('delete from entries WHERE id = ?', [postID])
flash('Entry was deleted')
return redirect(url_for('show_entries', post=post))
In the html:
<h3>delete</h3>
Clicking <a href...>delete</a> will issue a GET request, and your delete_entry method only responds to POST.
You need to either 1. replace the link with a form & submit button or 2. have the link submit a hidden form with JavaScript.
Here's how to do 1:
<form action="/delete/{{ entry.id }}" method="post">
<input type="submit" value="Delete />
</form>
Here's how to do 2 (with jQuery):
$(document).ready(function() {
$("a.delete").click(function() {
var form = $('<form action="/delete/' + this.dataset.id + '" method="post"></form>');
form.submit();
});
});
...
Delete
One thing you should not do is make your delete_entry method respond to GET. GETs are meant to be idempotent (are safe to run repeatedly and don't perform destructive actions). Here's a question with some more details.
Alternatively, change POST to DELETE to get you going.
#app.route('/delete/<postID>', methods=['DELETE'])
Ideally, you should use HTTP DELETE method.
I used flaskr as a base for my Flask project (as it looks like you did as well).
In the .py:
#app.route('/delete', methods=['POST'])
def delete_entry():
if not session.get('logged_in'):
abort(401)
g.db.execute('delete from entries where id = ?', [request.form['entry_id']])
g.db.commit()
flash('Entry deleted')
return redirect(url_for('show_entries'))
In the HTML:
<form action="{{ url_for('delete_entry') }}" method=post class=delete-entry>
<input type="hidden" name="entry_id" value="{{ entry.id }}">
<input type="submit" value="Delete" />
</form>
I wanted a button, but you could easily use a link with the solution here.
A simple <a href= link in HTML submits a GET request, but your route allows only PUT requests.
<a> does not support PUT requests.
You have to submit the request with a form and/or with JavaScript code.
(See Make a link use POST instead of GET.)
I have this in my views.py file as the view config for my home page:
#view_config(route_name='home_page', renderer='templates/edit.pt')
def home_page(request):
if 'form.submitted' in request.params:
name= request.params['name']
body = request.params['body']
page=Page(name,body)
DBSession.add(page)
return HTTPFound(location=request.route_url('view_page',pagename=name))
return {}
Also, here is the form in the edit.pt template:
<form action="/view_page" method="post">
<div>
<input type="text" name="name"/>
</div>
<div>
<input type="text" name="body"/>
</div>
<label for="stl">Stl</label>
<input name="stl" type="file" value="" />
<input type="submit" name='form.submitted' value="Save"/>
</form>
Also in my init.py file I have
config.add_route('home_page', '/')
config.add_route('view_page', '/{pagename}')
right now when I submit the form it just tries to go to localhost:6543/view_page. This returns a 404 as there is no view_page resource or route leading to it. Instead I want it to go to localhost:6543/(the name of the page I just created aka the first input box in the form). How can I do this?
Edit: I am worried that something else may be telling it to route to view_page because I even tried changing it to
return HTTPFound(location=request.route_url('front_page',pagename=name))
And it still goes to /view_page. There is no route named front_page, so I would at least suspect it to throw an error.
Also, I would really appreciate it if you could tell me where you found the info. I have been looking at http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/api/request.html?highlight=request.route_url#pyramid.request.Request.route_url but can't seem to find use from it.
Edit: should I be using an asset specification instead of a path name? so
return HTTPFound(Location=request.route_url('tutorial:templates/view.pt','/{pagename}'))
Also, I am working through this article which seems very helpful with the syntax: http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/urldispatch.html#urldispatch-chapter
I think your form should submit to "/", ie.
<!-- where your home_page route is waiting for the POST -->
<form action="/" method="post">
With the prior answers this now looks correct:
return HTTPFound(location=request.route_url('view_page', pagename=name))
My first guess is that it's location not Location as the argument to HTTPFound.
from the link you give
it's should be
return HTTPFound(location=request.route_url('view_page',pagename=name))
when you had add this route
config.add_route('view_page', '/{pagename}')
and set the variable name before
name= request.params['name']