Can't pass a variable with Jinja in Flask - python

The form's action sends the input to a route named soldfor. I am trying to pass the variable ID into soldfor. When I hit the submit button I get this error:
TypeError: soldfor() takes exactly 1 argument (0 given)
Rendering of register_results.html:
return render_template('register_results.html', results=results, ID=ID)
register_results.html:
<form role="form" method="POST" action="{{ url_for('soldfor', ID={{ ID }}) }}">
<div class="input-group">
<input type="number" class="form-control" placeholder="Sold For" autocomplete="off" name="soldfor">
<span class="input-group-btn">
<button class="btn btn-default" name="soldfor" value="soldfor" type="submit">Sell!</button>
</span>
</div>
</form>
soldfor Route:
#app.route("/soldfor", methods=["POST"])
def soldfor(ID):
soldfor = request.form['soldfor']
print(soldfor)
g.db = connect_db()
g.db.execute("UPDATE yardsale SET SF = ? WHERE ID = ?", (soldfor, ID,))
g.db.commit()
g.db.close()
return redirect(url_for('index'))

You need to change this:
<form role="form" method="POST" action="{{ url_for('soldfor', ID={{ ID }}) }}">
to this:
<form role="form" method="POST" action="{{ url_for('soldfor', ID=ID) }}">
Also from the documentation:
When you define a route in Flask, you can specify parts of it that
will be converted into Python variables and passed to the view
function.
#app.route('/user/<username>')
def profile(username):
pass
Whatever is in the part of the URL labeled will get passed
to the view as the username argument. You can also specify a converter
to filter the variable before it’s passed to the view.
#app.route('/user/id/<int:user_id>')
def profile(user_id):
pass
Your error is being caused by the route expecting a parameter, but you are not passing one in. You should probably use something like that last example to accomplish what you're trying to do.
It's also sometimes desirable to pass a default value into the view function in case you need to use that URL without passing an ID. An example would look like this:
#app.route('/user/id/<int:user_id>')
def profile(user_id=0):
pass

Related

How to pass the value to html input by add optional parameters to the link of the website to turn it into an API (flask)

I'm new to flask and I wonder how to pass the value to the HTML by adding optional parameters into the link
Example HTML:
<HTML>
<body>
<form method=post enctype=multipart/form-data>
<input type=text name=link>
<input type=submit value=Open>
</form>
</body>
</HTML>
Code I'm using to call the HTML above:
#app.route('/link', methods=['GET', 'POST'])
def open_link():
if request.method == "POST":
if 'link' != '':
text = request.form['link']
webbrowser.open(text)
return render_template("get_link.html")
Now, I want to add a parameter to the link to automatically pass the value for the input in, so that I can make it into an API
Example
http://192.168.5.107:8000/link/**add_para_here = hi**
Any suggestion? and only sorry for my bad English.Thank you
If I understand you correctly, you would like to use optional url parameters within your request. So that the url can be created in the following way.
http://127.0.0.1:8000/link?param0=value0&param1=1
In this case the form would look like this.
<form action="{{ url_for('link', param0='value1', param1=1) }}" method="post">
<input type="text" name="link">
<input type="submit" value="Open">
</form>
Within the endpoint, the parameters can be queried via request.args. Default values and an optional type conversion can also be specified here.
#app.route('/link', methods=['GET', 'POST'])
def open_link():
param0 = request.args.get('param0')
param1 = request.args.get('param1', 0, type=int)
if request.method == "POST":
if 'link' != '':
text = request.form['link']
# ...
return render_template("get_link.html")
Have fun implementing your project.

Django form input and action linking

How do you pass form inputs to a form action in Django? I tried this but it's not working
<form action="/search?search_term=q" method="get">
<input type="text" name="q">
<input type="submit" value="Search">
</form>
I'm assuming you're asking how to link an HTML form to a view function for processing. Note that in Django, we don't call them actions.
Here's the basic form and placeholder for the search results that you'd put in a Django template:
<form action="/search" method="get">
<input type="text" name="q">
<input type="submit" value="Search">
</form>
{% if search_results %}
Display search results here.
{% endif %}
If you type apple into the text field and then click the search button on this form it will make a GET request to /search?q=apple.
You will need to route the request via a URLconf to a view function to do the processing.
The entry in the URLconf may look like the following:
from django.conf.urls import url
from app import views
urlpatterns = [
# ...
url(r'^search/$', views.search),
# ...
]
views.search is the view function that does the processing. Here's a possible implementation:
from django.shortcuts import render
def search(request):
q = request.GET.get('q')
if q is None:
return render(request, 'app/search.html')
search_results = perform_search(q)
context = { 'search_results': search_results }
return render(request, 'app/search.html', context)
Where perform_search is a function you'd need to write to do the actual searching.
When you specify a method GET in form, then You don't need to append parameters explicitly in the URL. When the user submits the form your parameter will automatically append in the URL as key-value pairs.
Example
<form action="search" method="GET">
<input type="text" name="search_item1">
<input type="text" name="search_item2">
<input type="submit" value="Search">
</form>
When a user hit submit button then your parameter(serach_item1 and serach_item2) will append implicitly in action URL. where keys are input fields name attribute
Now your URL looks like
www.example.com/search?search_item1=<serach1>&search_item2=<serach2>
To pass GET arguments to the page you don't need to specify it in action attribute.
Just do follow:
<form method="GET" action="search/">
<input type="text" name="search_term" value="{{ request.GET.search_term }}">
<input type="submit" value="Search">
</form>
this will redirect you to the page http://yourdomain.com/search?search_term=search_text.
Please note I replaced input name attribute to rename GET argument to search_term. Also I added value attribute to display current search text to the input field.
shuboy2014 and neverwalkaloner are correct. But a fact they didn't tell you is that you'll pass empty values if you declare no values in that fields. For example:
<form method="GET" action="search/">
<input type="text" name="search_term">
<input type="submit" value="Search">
</form>
That would create an URL like http://yourdomain.com/search?search_term=, which could lead to unexpected errors in the View later. You either should do request.GET.get("search_term") to avoid exceptions or modify the submit function of your form to dinamically remove the names of those empty fields.

Flask - generate url with parameters in html

I am trying to find how I can pass a URL parameter (not request) into the url_for function, but I cant find it. In the following example, I need to pass the q_id through the form, as I do with incrRight. So, how can I have variables in url_for in this scenario ?
<form action="{{url_for('answer',q_id='5495eb77433f064294361ceb')}}" method="post">
<input type="text" name="incrRight" value="0">
<input type="submit"/>
</form>
This is what I have on my controller:
#app.route('/api/v1.0/question/<string:q_id>/answer', methods = ['POST'])
def answer(q_id):
incrRight = request.form.get('incrRight')
. . .
I need my html form to be able to communicate with the above function, by passing a q_id and the incrRight parameter.
You can add additional form parameters by adding more <input> tags. If the user of the form is not supposed to changed the items, use a <input type="hidden"> element:
<form action="{{ url_for('answer') }}" method="post">
<input type="text" name="incrRight" value="0" />
<input type="hidden" name="q_id" value="5495eb77433f064294361ceb" />
<input type="submit"/>
</form>
This does require that the answer() view can be invoked without the q_id parameter, of course:
#app.route('/api/v1.0/question/answer', methods=['POST'])
#app.route('/api/v1.0/question/<string:q_id>/answer', methods = ['POST'])
def answer(q_id=None):
if q_id is None:
q_id = request.form['q_id']
incrRight = request.form.get('incrRight')
Here a missing q_id parameter in the URL signals to the view that the browser included the question id in the POST body instead.
Another option is for you to write JavaScript code that'll adjust the form action parameter based on the q_id field in the form, but this then requires that your visitors have JavaScript enabled.

returning empty array from post request

I am trying to pass some dynamic values from my form, but so far I am only getting empty values.
I have an autocomplete plugin, where I search for "names" from a JSON object, each time I select one they will pass into a list with value="the ID".
I couldn't find a unordered list in WTForms, so I am using SelectMultipleField instead, since it is able to pass many values as an array/list
my form class is looking like this:
class ClassForm(Form):
function_name = StringField('names')
studentid = SelectMultipleField('studentid')
submit = SubmitField('submit')
then in my template I am using it like this
<form id="function_search_form" method="post" action="">
{{ form.csrf_token }}
{{form.function_name.label()}}
{{form.function_name()}}
<!-- then I am not using studentid directly,
but just normal html, so each time you pass
in a name from the json object it will come in like this.
-->
<ol class='student-list'>
<li value="1" name="studentid" id="studentid">test</li>
</ol>
{{ form.submit()}}
</form>
My problem is that it wont get the value from the list, even if I hard code the values directly, instead from the jquery script.
Here is how my view looks like
#app.route('/index', methods=['GET', 'POST'])
def index():
form = ClassForm()
if request.method == 'POST' and form.validate_on_submit():
flash('valid form')
st = form.studentid.data
print(st)#debug
return render_template('index.html', form=form)
Everytime I submit I am printing form.studentid.data I am getting [], which is an empty list.
Even when I try to pass single values and make studentid to a StringField I am still getting an empty value.
I have also tried the request.form['studentid'] but then I am getting Bad Request What am I doing wrong and is there another way to pass "custom" values ?
The reason its not working is because <li> is not a form control, so its data is not sent back with the form request.
You are never rendering the studentid field from your form class, so the form control is never rendered. It would be like expecting the following to work:
<form>
<p name="foo" data="hello">This should be sent</p>
<input type="submit">
</form>
To get the data back to your view method, you need to use a form control - you can test it out like this:
<form id="function_search_form" method="post" action="">
{{ form.csrf_token }}
{{form.function_name.label()}}
{{form.function_name()}}
<select name="studentid" class='student-list'>
<option value="1">test</option>
</select>
{{ form.submit()}}
</form>
Or, simply render the field correctly:
<form id="function_search_form" method="post" action="">
{{ form.csrf_token }}
{{form.function_name.label()}}
{{form.function_name()}}
{{form.studentid.label()}}
{{form.studentid}}
{{ form.submit()}}
</form>

Django: Template {% url %} tag, how to pass parameter from form

There is template:
<form action="{% url 'nfoapp.views.kinoscrap' <I WANT MOVIE_ID THERE> selectshort.id %}" method="post">
<input type="text" class="form-control" name="MOVIE_ID">
<button type="submit" class="btn btn-danger">Kinopoisk Search by ID</button>
</form>
There is my urls.py:
(r'^kinoscrap/(?P<kinoid>\d+)/(?P<shortid>\d+)/$', kinoscrap),
I want pass to kinoscrap two parameters - text field from form (MOVIE_ID) and 'selectshort.id' variable. The problem is that i can't put simple MOVIE_ID in first line of template, I got error. But when I try put instead MOVIE_ID other variable, for example selectshort.id, program work without error.
How I can trasmit text field value to view?
p.s I use bootstrap, if it has some importance.
You could have the form action empty, so to the same view, and then in the view redirect using the POST data from the form.
<form action="" method="post">
<input type="text" class="form-control" name="MOVIE_ID">
<button type="submit" class="btn btn-danger">Kinopoisk Search by ID</button>
</form>
And then in the view
def searchView(request):
if request.method == 'POST':
# get variables from form and redirect
else:
# do your normal rendering
(r'^kinoscrap/(?P<kinoid>\d+)/(?P<shortid>\d+)/$', kinoscrap),
Your urls.py accepts to integer values in the url (something like kinnoscrap/12/21), if you pass anything beside integers it'll throw an error. If you want to pass a text field you'll have to change the regular expression.
Try out your regexes at regex101 here to see if they'll work.

Categories