this is more of a question about where to find how I would do this rather than asking how to do this. I'm sure this is well covered, I'm just struggling to articulate the correct term which I could use to Google and find out the answer.
Anyway - I have a Python Flask web application. On a web page, there is an input box which requests user input. What I would like to happen, is for some magic to happen with the user input in the background. In my own scenario, I would like to take a URL, then use bs4 to pick off what I need and display this on the web page.
For simplicity, I'll ask for something for simple and I can then build on it from there: if I were to request the user to specify a number then press 'Submit', how could I multiply the number by 10?
If my code for the form was index.html:
<form class="form-horizontal" role="form" method="post" action="/">
{{ form.csrf_token }}
<fieldset>
<div class="form-group">
<label for="GetNum" class="col-lg-2 control-label">Enter Number</label>
<div class="col-lg-6">
<input type="text" id="GetNum" name="GetNum" class="form-control" value="">
</div>
<input class="btn btn-success" type="submit" value="Calculate">
</div>
</fieldset>
</form>
I noticed that I can get the input to print to a paragraph by <p>form.request.GetNum</p>.
Now for this question's example, the code for the backend functionality will be:
import math
GetNum = 10 #should be form.request.GetNum value
CalcResult = GetNum*1000
print CalcResult # or {{ CalcResult.data }} or something in index.html
My Controller (app.py) looks like:
#app.route('/', methods=['GET', 'POST'])
#login_required
def home():
error = None
form = PostForm(request.form) # unrelated to question, but will this clash?
if .. :
do something
return redirect(..)
else:
do something else..
return render_template(..)
My worry is that the home function will end up having a mass of code if I have to put the math function in there. So tl;dr, how would I implement a back end function within my code? (or please provide me with material to read, thank you!)
One other thing is I already have a form on my '/' page, will I have to rename the forms like form1 form2 because they will clash or will it be OK?
Elsewhere in your code base, either in the same file, or more likely
a module or package you could define that complicated task. Lets
create a simple module complicated.py in the same directory as your
other code, that then defines the complicated task:
def do_really_complicated_thing(info):
# lots of complicated steps
return really_complicated_data
Then in our view code, we can just use that instead of having it embedded:
from complicated import do_really_complicated_thing
#app.route('/', methods=['GET', 'POST'])
#login_required
def home():
error = None
form = PostForm(request.form)
if form.validate_on_submit() :
info = form.info.data
complicated_task = do_really_complicated_thing(info)
return render_template('something', results=complicated_task)
So, in short-- the terms you're looking for is packages and modules, they
help your code be neater and reusable.
As for clashing forms— you can just target the form to post to a specific route which just handles that form, which is much cleaner then then having to validate/parse different forms in a single route.
Related
I'm trying to create a dynamic URL based on user's input from an HTML form.
For example, if a user types in 'AAPL' or 'KO', the next page should be:
webapp.com/result/AAPL or webapp.com/result/KO
index.html:
<div class="cell" id="cell-1-2">
<span class="data" style="text-align: center;">
<form action="{{ url_for('ticker_result', variable='variable') }}" method="POST">
<input type="text" name="variable" placeholder="search ticker or company" maxlength="4"
font-size="24px" style="text-transform:uppercase">
<input class="button" type="submit" value="Search" onclick="tickerSymbol();">
</form>
</span>
</div>
I've tried renaming the 'variable' part to several different things and nothing works so I'm just stuck at this point.
main.py:
# Routing to the homepage
#app.route("/")
def markert_hours_today():
return render_template(
"index.html")
# Routing to the result page
#app.route("/result/<variable>", methods = ["GET", "POST"])
def ticker_result(variable):
if request.method == "POST":
result = request.form["variable"]
return render_template(
"result.html",
result=result)
When I run the local environment, and type in a ticker symbol, the next URL is:
webapp.com/result/variable
I'm assuming it's HTML that I need to edit? I've read the quickstart documentation for Flask which isn't making sense to me and looked up similar questions but I can't seem to find an answer to this.
You are coming at it from the wrong way. When Jinja creates index.html based on your template you can't know what variable is going to be, so how is Jinja supposed to know?
What you need to do is send the form back to the same route and then redirect the user to whatever they typed in. So something like this:
from flask import request, redirect, url_for
#app.route("/", methods=['GET', 'POST'])
def markert_hours_today():
if request.method == 'POST':
result = request.form['variable']
return redirect(url_for('ticker_result', variable=result)
return render_template("index.html")
Edit: forgot to rename variable from user_input to result.
I am building a web-app using flask where I am trying to route some URLs
I have three routes with me
a) "/"
b) "/teacher"
c) "/student"
The routing works fine for "/" and"/student" The URL gets appended after clicking the submit button for student and"/student" gets appended in URL but on clicking the button associated with "/teacher" the URL doesn't gets appended and "/" page keeps on loading up.
Please help me out here and tell me what wrong I am doing
My Python code:
#app.route('/', methods=['GET', 'POST'])
def select():
return render_template("select.html")
#app.route('/teacher', methods=['GET', 'POST'])
def index():
return render_template("index_teacher.html", title="Faculty login")
#app.route('/student', methods=['GET', 'POST'])
def index1():
return render_template("index_student.html", title="Student login")
Part of my html code from select.html:
<form action="/teacher" method = "post">
<input type="submit" class="submit" value="Login as Teacher">
</form>
<br>
<form action="/student" method="post">
<input type="submit" class ="submit" value="Login as Student">
</form>
One more thing about the code, when I add a text box above the first submit button, both the button starts working and give desired results.
Thanks in advance!
I think you have just a little typo in the html. The input tag of teacher didn't close >.
<form action="/teacher" method = "post">
<input type="submit" class="submit" value="Login as Teacher">
</form>
<br>
<form action="/student" method="post">
<input type="submit" class ="submit" value="Login as Student">
</form>
EDIT:
In the case that the question was copied incorrectly, I don't know what should be wrong with your code. For me your sample code works just fine. So from my experience with flask and html forms the most common errors I made are the following, maybe it's one of them (the list may serve other too, so I will also add points that do not make sense for your case):
method name of two routes collide (e.g. both '/' and '/teacher' are assigned to function index, but that should give an error when starting the server, so not really possible)
an html tag is not closed properly, so the form in question is not parsed as a valid form (that was my guess with above answer, also makes sense with the text box, which may close the corrupt tag => in html an open tag is closed by the first following closing tag)
typo in the form action attribute (check the network tab in your browsers developer tools, maybe you get an error response to something like "taecher", which results in a redirect to "/", again not really plausible with the fact that it suddenly works when you add the text box)
typo in the route or the returned template (again not plausible with explained behavior with the added text box)
That's all I can think of at the moment. I hope it helps with the search. if you could add more of your html code, maybe I find something suspicious.
My question is similar to Replacing input() portions of a Python program in a GUI. But I need a web UI not desktop UI(tkinter based solution as answered in the link)
You will have to create a webpage with HTML/CSS and create a form in it to get the input. Then, you will have to link the webpage with your backend (flask) to receive the input in python and manipulate as needed. Following a tutorial like this one will help you get started. Or, you can simply search the web for "Form handling in Flask" to find something that suits your needs.
Say you're asking for the user to input their username. You'd do something like this.
HTML
<body>
<form action="" method="post">
<input type="text" placeholder="" value="{{ request.form.username }}">
<input type="submit" value="Submit">
</form>
</body>
Whatever you want to call your variable, you put after request.form
In your program (where you import flask), also import request from flask like so:
from flask import request
Under your route's function, check if the request's method is POST and assign your form variable:
def index():
if request.method == "POST":
foo = request.form["username"]
return render_template("index.html")
So when the user clicks the submit button, foo will be whatever they put in the text box.
You can see more at https://flask.palletsprojects.com/en/1.1.x/quickstart/#accessing-request-data
I'm using Pyramid to build a webapp, and I've got two views where one leads to the other:
config.add_route("new", "/workflow/new")
config.add_route("next", "/workflow/{id}/next")
The new view is really very simple and presents only an HTML form as a Jinja2 template for the user to fill in some information:
<form method="post" action="{{ request.route_url('next',id='') }}" >
<input type="text" name="id" value="Identifier" />
...
<input type="submit" name="next" value="Next" />
</form>
The question here regards the action of that form: how can I use the content of the text input field id, perhaps process it a little, and then pass it on in the route request?
Note that in this scenario the form data is passed from the new view to the next view, and that should stay the same.
When the form is posted, the forms fields will be available in the request object, see
http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/webob.html#request
I believe it is also a good idea to post to the same url (<form action="#" method="post">), so that you can validate the form. Then you can process and redirect to the next url when the form is valid, or recreate the form with errors if it isn't.
So your view may end up something like this;
from pyramid.httpexceptions import HTTPFound
from pyramid.url import route_url
def myview(request):
if request.method == 'POST':
# Validate the form data
if <form validates successfully>:
# Do any processing and saving here.
return HTTPFound(location = route_url('next', id=request.params['id'], request=self.request))
else:
request.session.flash("The form isn't valid.")
# Do some stuff here to re-populate your form with the request.params
return { # globals for rendering your form }
There are already many questions/answers addressing this, such as How can I redirect after POST in Pyramid?
I'm currently working on a pyramid project, however I can't seem to submit POST data to the app from a form.
I've created a basic form such as:
<form method="post" role="form" action="/account/register">
<div class="form-group">
<label for="email">Email address:</label>
<input type="email" class="form-control" id="email" placeholder="you#domain.com">
<p class="help-block">Your email address will be used as your username</p>
</div>
<!-- Other items removed -->
</form>
and I have the following route config defined:
# projects __init__.py file
config.add_route('account', '/account/{action}', request_method='GET')
config.add_route('account_post', '/account/{action}', request_method='POST')
# inside my views file
#view_config(route_name='account', match_param="action=register", request_method='GET', renderer='templates/account/register.jinja2')
def register(self):
return {'project': 'Register'}
#view_config(route_name='account_post', match_param="action=register", request_method='POST', renderer='templates/account/register.jinja2')
def register_POST(self):
return {'project': 'Register_POST'}
Now, using the debugger in PyCharm as well as the debug button in pyramid, I've confirmed that the initial GET request to view the form is being processed by the register method, and when I hit the submit button the POST request is processed by the *register_POST* method.
However, my problem is that debugging from within the *register_POST* method, the self.request.POST dict is empty. Also, when I check the debug button on the page, the POST request is registered in the list, but the POST data is empty.
Am I missing something, or is there some other way of access POST data?
Cheers,
Justin
I've managed to get it working. Silly me, coming from an ASP.NET background forgot the basics of POST form submissions, and that's each form field needs a name== attribute. As soon as I put them in, everything started working.
That does nothing, I belive.
return {'project': 'Register_POST'}
POST parameters are stored inside request, so you have to do something like this.
def register_POST(self, request):
return {'project': request.POST}
To access email input (which has to be named, for example: name="email"), use get() method:
request.POST.get('email')
<form method="post" role="form" action="/account/register"> {% csrf_token %}
Try using "csrf token". hope it works. remaining code looks fine.