flask-wtf behavior with 2 forms in view - python

example 2 forms in one page:
<form name="form_A" class="form-inline" action="/" method="post">
{{form_A.hidden_tag()}}
{{form_A.name(type="text", class="form-control")}}
<input type="submit" name="form_A" id="form_A" class="btn btn-sm btn-success" value="FORM_A">
</form>
<form name="form_B" class="form-inline" action="/" method="post">
{{form_B.hidden_tag()}}
{{form_B.name(type="text", class="form-control")}}
<input type="submit" name="form_A" id="form_A" class="btn btn-sm btn-success" value="FORM_B">
</form>
and router:
#app.route('/', methods = ['GET', 'POST'])
def index():
form_A = ExampleForm1(request.form)
form_B = ExampleForm1(request.form)
if form_A.validate_on_submit():
...
if form_B.validate_on_submit():
...
any submit button (FORM_A or B) call form_A.validate_on_submit() and form_B.validate_on_submit() together(!). why?
and how to submit only one form in this case?
EDIT:
i solve this problem just add check data any field and use is_submitted method:
if form_A.is_submittied() and form_A.name.data:
...

When using more than one form, you need to give each form a prefix:
form_A = ExampleForm1(request.form, prefix='form_a')
form_B = ExampleForm1(request.form, prefix='form_b')

Related

I am creating a search function in django but it isn't working

I am trying to create a function to search for objects in base.html from the database using a keyword and printing the results in listing.html
base.html
<form method="post" action="{% url 'listing'}" name="searchform">
{% csrf_token %}
<div class="custom-form">
<label>Keywords </label>
<input type="text" placeholder="Property Keywords" name="search_keyword" value=""/>
<label >Categories</label>
<select data-placeholder="Categories" name = "home_type" class="chosen-select on-radius no-search-select" >
<option>All Categories</option>
<option>Single-family</option>
<option>Semi-detached</option>
<option>Apartment</option>
<option>Townhomes</option>
<option>Multi-family</option>
<option>Mobile/Manufactured</option>
<option>Condo</option>
</select>
<label style="margin-top:10px;" >Price Range</label>
<div class="price-rage-item fl-wrap">
<input type="text" class="price-range" data-min="10000" data-max="100000000000" name="price-range1" data-step="1" value="1" data-prefix="$₦">
</div>
<button onclick="location.href='listing'" type="button" class="btn float-btn color-bg"><i class="fal fa-search"></i> Search</button>
</div>
</form>
views.py
def listing(request):
global search_keyword
p = Paginator(Property.objects.order_by('-listed_on'), 2)
page = request.GET.get('page')
propertys = p.get_page(page)
nums = "p" * propertys.paginator.num_pages
if request.method == 'POST' and 'searchform' in request.POST :
search_keyword = request.POST['search_keyword']
propertys = Property.objects.filter(name__contains=search_keyword)
return render(request, 'listing.html',{'nums':nums, 'search_keyword':search_keyword, 'propertys':propertys})
return render(request, 'listing.html',{'nums':nums,'propertys':propertys})
Your syntax of url[django-doc] tag is wrong, it must be {% url 'listing' %} not {% url 'listing'}, you forget to add % at the end which is not the syntax of django template language.
Try this:
Template file:
<form method="POST" action="{% url 'listing' %}" name="searchform">
You can also make use of __icontains for case-insensitive.

How do I in Flask get what of two buttons in same form has been clicked to perform different actions?

I have a single input field where I wan't 2 buttons with different actions.
<!-- Search box -->
<input type="text" class="form-control mb-2 mr-sm-2" placeholder="UserID" name="search"
aria-describedby="useridHelp" required pattern="[0-9]{5,7}">
<!-- Submit/Update button -->
<button id="add-update" type="button" class="btn btn-primary mb-2 mr-2">Add/Update</button>
<!-- Remove button -->
<button id="remove" type="button" class="btn btn-primary mb-2">Remove</button>
If I make the "add-update" button to a type="submit" and use if request.method == 'POST': in Flask then I Submit the value of the field. Great.
But how do I call the "remove" button into Flask so I can give it a function?
In other words. When a user click the "Add/Update button" the field input should be added to my database. When a user click the "Remove" button the field input should be deleted from my database.
How do I grab which button has been clicked in Flask?
I found the solution here: https://predictivehacks.com/?all-tips=how-to-add-action-buttons-in-flask
The answer is to do:
if request.form.get('action1') == 'VALUE1':
The example is:
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route("/", methods=['GET', 'POST'])
def index():
if request.method == 'POST':
if request.form.get('action1') == 'VALUE1':
pass # do something
elif request.form.get('action2') == 'VALUE2':
pass # do something else
else:
pass # unknown
elif request.method == 'GET':
return render_template('index.html', form=form)
return render_template("index.html")
<h3>Our Flask Buttons<h3/>
<form method="post" action="/">
<input type="submit" value="VALUE1" name="action1"/>
<input type="submit" value="VALUE2" name="action2" />
</form>
HTML Change:
You can have a form, with one text box and two buttons. The button names are the same(two_buttons) and will have different values(add-update and remove, which will be used in the flask to identify them.
two_button_add_and_remove.html
<form action="{{ url_for('check_button')}}" method="POST">
<!-- Search box -->
<input type="text" class="form-control mb-2 mr-sm-2" placeholder="UserID" name="search"
aria-describedby="useridHelp" required pattern="[0-9]{5,7}">
<!-- Submit/Update button -->
<button name="two_buttons" value="add-update" id="add-update" type="submit" class="btn btn-primary mb-2 mr-2">Add/Update</button>
<!-- Remove button -->
<button name="two_buttons" value="remove" id="remove" type="submit" class="btn btn-primary mb-2">Remove</button>
</form>
Now in Flask, check the value of request.form['two_buttons'] and based on it call your add or remove function with parameter request.form['search']
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route('/check_button', methods=['GET','POST'])
def check_button():
print("Request.method:", request.method)
try:
if request.form['two_buttons'] == "add-update": # check if value is "add-update"
print(f"call add-update_function with {request.form['search']}")
else:
print(f"call remove_function with {request.form['search']}")
return render_template('two_button_add_and_remove.html')
except Exception as e:
return render_template('two_button_add_and_remove.html')
if __name__ == '__main__':
app.run(debug=True)

Django form with checkbox is always False

I'm looking to create a Django form with a checkbox.Irrespective of weather I check or uncheck the box,it is not detected in POST request.Here is the code of the template-
<form action="annotate_page" method="post">{% csrf_token %}
<input id="repeat" type="checkbox" >
<label for="repeat">Repeat Sentence?</label>
<br>
<button type="submit">Next</button><br>
</form>
Here is my forms.py-
from django import forms
class AnnotateForm(forms.Form):
repeat=forms.BooleanField(required=False)
Here is my views logic-
if request.method=="POST":
form = AnnotateForm(request.POST)
if form.is_valid():
print(request.POST)#prints only csrf_token in Query_dict
print(form.cleaned_data["repeat"])#Always false
Irrespective of weather the checkbox is checked or not,the print statement always gives False.
I know there are questions similar,but they don't solve my problem.
<form action="annotate_page" method="post">{% csrf_token %}
<input id="repeat" name="something" type="checkbox" >
<label for="repeat">Repeat Sentence?</label>
<br>
<button type="submit">Next</button><br>
</form>
and in view
if request.method=="POST":
form = AnnotateForm(request.POST)
if form.is_valid():
print(request.POST)#prints only csrf_token in Query_dict
print(form.cleaned_data["something"])#Always false
you need to give a name in the input field or else it wont be captured

How to call a different render after a form submission

I'm diving into Flask for the first time and I'm having some trouble getting something work.
I currently have a template for when my tab values is empty, it contains a form that when submitted should call a specific function using the parameters of the form and return another template. Each call of the form should in, fact call the index.html template with different values.
Relevant parts of code are as follows:
main.py
#app.route('/', methods=['POST','GET'])
def main():
global maxDepth, numberOfRelated
if not values:
return render_template('initial.html')
if request.method=='POST':
url = request.form['url']
maxDepth = request.form['depth']
numberOfRelated = request.form['numberOfRelated']
values = crawling(url,maxDepth,numberOfRelated)
return render_template('index.html',var=values)
The form part of initial.html and index.html are actually the same
<form class="form-inline" action="/" method="POST">
<div class="form-group">
<input name='url' type="text" class="form-control"/>
</div>
<div class="form-group minorForm">
<input name='numberOfRelated' type="text" class="form-control" />
</div>
<div class="form-group minorForm">
<input name='depth' type="text" class="form-control" />
</div>
<div class="form-group navbar-right">
<button class="btn btn-success minorForm generate" type="submit"> Generate</button>
</div>
</form>
In your main method, unless values is global, it won't be defined for if not values.
As to your question, add another render_template call just after the conditional for if the form was submitted:
if request.method=='POST':
url = request.form['url']
maxDepth = request.form['depth']
numberOfRelated = request.form['numberOfRelated']
values = crawling(url,maxDepth,numberOfRelated)
return render_template('index.html',var=values) # 1
return render_template('index.html',var=values) # 2
If the form is submitted, the conditional will be true and the template will be rendered at comment #1. If the user is navigating to the page normally, the conditional will be false and the line with comment #2 will be called.
I'm a bit confused about the question, but you should always redirect after a POST (unless there was an error in the form and no action was taken). That way the same action won't be repeated if the user reloads the page.

flask - url with searched word

I want to ask how to make my urls to include the worh that I searched. Something like this:
http://host/filter?test
My code:
#app.route('/filter', methods=['POST', 'GET'])
def filter():
if request.method == 'POST':
if str(request.form['search_string']) <> '':
api.queryMessage(request.form['search_string'])
return render_template('main.html', search_string=search_string)
And my template, main.html:
<form name="filters" action="{{ url_for('filter') }}" method=post id="filters">
<div style="position: absolute; top:100px; left:300px">
<p>Search string: <input type=text size=80 title="Match all of the words" name=search_string value="{{search_string}}"></p>
<input type=submit value=Filter/Search onclick=loopSelected();>
<input type="hidden" name="chosen" id="chosen" value="{{chosen}}" />
</div>
</form>
You're now using POST request. Use GET request, so browser will put your form values to URL.
in HTML form set method="GET":
<form name="filters" action="{{ url_for('filter') }}" method="GET" id="filters">
You'll get URL in the following form:
http://host/filter?search_string=test&chosen=<id>&<some other trash>
In Flask use request.args instead of request.form:
if request.method == 'GET':
if request.args.get('search_string'):
...

Categories

Resources