I have multiple form on the same page that send post request to same handler
in flask.
I am generating forms using wtforms.
what is the best way to identify which form is submitted ?
I am currently using action="?form=oneform". I think there should be some better method
to achieve the same?
The solution above have a validation bug, when one form cause a validation error, both forms display an error message. I change the order of if to solve this problem.
First, define your multiple SubmitField with different names, like this:
class Form1(Form):
name = StringField('name')
submit1 = SubmitField('submit')
class Form2(Form):
name = StringField('name')
submit2 = SubmitField('submit')
....
Then add a filter in view.py:
....
form1 = Form1()
form2 = Form2()
....
if form1.submit1.data and form1.validate(): # notice the order
....
if form2.submit2.data and form2.validate(): # notice the order
....
Now the problem was solved.
If you want to dive into it, then continue read.
Here is validate_on_submit():
def validate_on_submit(self):
"""
Checks if form has been submitted and if so runs validate. This is
a shortcut, equivalent to ``form.is_submitted() and form.validate()``
"""
return self.is_submitted() and self.validate()
And here is is_submitted():
def is_submitted():
"""Consider the form submitted if there is an active request and
the method is ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.
"""
return _is_submitted() # bool(request) and request.method in SUBMIT_METHODS
When you call form.validate_on_submit(), it check if form is submitted by the HTTP method no matter which submit button was clicked. So the little trick above is just add a filter (to check if submit has data, i.e., form1.submit1.data).
Besides, we change the order of if, so when we click one submit, it only call validate() to this form, preventing the validation error for both form.
The story isn't over yet. Here is .data:
#property
def data(self):
return dict((name, f.data) for name, f in iteritems(self._fields))
It return a dict with field name(key) and field data(value), however, our two form submit button has same name submit(key)!
When we click the first submit button(in form1), the call from form1.submit1.data return a dict like this:
temp = {'submit': True}
There is no doubt when we call if form1.submit.data:, it return True.
When we click the second submit button(in form2), the call to .data in if form1.submit.data: add a key-value in dict first, then the call from if form2.submit.data: add another key-value, in the end, the dict will like this:
temp = {'submit': False, 'submit': True}
Now we call if form1.submit.data:, it return True, even if the submit button we clicked was in form2.
That's why we need to define this two SubmitField with different names. By the way, thanks for reading(to here)!
Update
There is another way to handle multiple forms on one page. You can use multiple views to handle forms. For example:
...
#app.route('/')
def index():
register_form = RegisterForm()
login_form = LoginForm()
return render_template('index.html', register_form=register_form, login_form=login_form)
#app.route('/register', methods=['POST'])
def register():
register_form = RegisterForm()
login_form = LoginForm()
if register_form.validate_on_submit():
... # handle the register form
# render the same template to pass the error message
# or pass `form.errors` with `flash()` or `session` then redirect to /
return render_template('index.html', register_form=register_form, login_form=login_form)
#app.route('/login', methods=['POST'])
def login():
register_form = RegisterForm()
login_form = LoginForm()
if login_form.validate_on_submit():
... # handle the login form
# render the same template to pass the error message
# or pass `form.errors` with `flash()` or `session` then redirect to /
return render_template('index.html', register_form=register_form, login_form=login_form)
In the template (index.html), you need to render both forms and set the action attribute to target view:
<h1>Register</h1>
<form action="{{ url_for('register') }}" method="post">
{{ register_form.username }}
{{ register_form.password }}
{{ register_form.email }}
</form>
<h1>Login</h1>
<form action="{{ url_for('login') }}" method="post">
{{ login_form.username }}
{{ login_form.password }}
</form>
I've been using a combination of two flask snippets. The first adds a prefix to a form and then you check for the prefix with validate_on_submit(). I use also Louis Roché's template to determine what buttons are pushed in a form.
To quote Dan Jacob:
Example:
form1 = FormA(prefix="form1")
form2 = FormB(prefix="form2")
form3 = FormC(prefix="form3")
Then, add a hidden field (or just check a submit field):
if form1.validate_on_submit() and form1.submit.data:
To quote Louis Roché's:
I have in my template :
<input type="submit" name="btn" value="Save">
<input type="submit" name="btn" value="Cancel">
And to figure out which button was passed server side I have in my views.py file:
if request.form['btn'] == 'Save':
something0
else:
something1
A simple way is to have different names for different submit fields. For an
example:
forms.py:
class Login(Form):
...
login = SubmitField('Login')
class Register(Form):
...
register = SubmitField('Register')
views.py:
#main.route('/')
def index():
login_form = Login()
register_form = Register()
if login_form.validate_on_submit() and login_form.login.data:
print "Login form is submitted"
elif register_form.validate_on_submit() and register_form.register.data:
print "Register form is submitted"
...
As the other answers, I also assign a unique name for each submit button, for each form on the page.
Then, the flask web action looks like below - note the formdata and obj parameters, which help to init / preserve the form fields accordingly:
#bp.route('/do-stuff', methods=['GET', 'POST'])
def do_stuff():
result = None
form_1 = None
form_2 = None
form_3 = None
if "submit_1" in request.form:
form_1 = Form1()
result = do_1(form_1)
elif "submit_2" in request.form:
form_2 = Form2()
result = do_2(form_2)
elif "submit_3" in request.form:
form_3 = Form3()
result = do_3(form_3)
if result is not None:
return result
# Pre-populate not submitted forms with default data.
# For the submitted form, leave the fields as they were.
if form_1 is None:
form_1 = Form1(formdata=None, obj=...)
if form_2 is None:
form_2 = Form2(formdata=None, obj=...)
if form_3 is None:
form_3 = Form3(formdata=None, obj=...)
return render_template("page.html", f1=form_1, f2=form_2, f3=form_3)
def do_1(form):
if form.validate_on_submit():
flash("Success 1")
return redirect(url_for(".do-stuff"))
def do_2(form):
if form.validate_on_submit():
flash("Success 2")
return redirect(url_for(".do-stuff"))
def do_3(form):
if form.validate_on_submit():
flash("Success 3")
return redirect(url_for(".do-stuff"))
I haven't used WTForms but should work regardless. This is a very quick and simple answer; all you need to do is use different values for the submit button. You can then just do a different def based on each.
In index.html:
<div>
<form action="{{ url_for('do_stuff')}}" method="POST">
<h1>Plus</h1>
<input type = "number" id = "add_num1" name = "add_num1" required><label>Number 1</label><br>
<input type = "number" id = "add_num2" name = "add_num2" required><label>Number 2</label><br>
<input type = "submit" value = "submit_add" name = "submit" ><br>
</form>
<p>Answer: {{ add }}</p>
</div>
<div>
<form action="{{ url_for('do_stuff')}}" method="POST">
<h1>Minus</h1>
<input type = "number" id = "min_num1" name = "min_num1" required><label>Number 1</label><br>
<input type = "number" id = "min_num2" name = "min_num2" required><label>Number 2</label><br>
<input type = "submit" value = "submit_min" name = "submit"><br>
</form>
<p>Answer: {{ minus }}</p>
</div>
in app.py:
#app.route('/',methods=["POST"])
def do_stuff():
if request.method == 'POST':
add = ""
minus = ""
if request.form['submit'] == 'submit_add':
num1 = request.form['add_num1']
num2 = request.form['add_num2']
add = int(num1) + int(num2)
if request.form['submit'] == 'submit_min':
num1 = request.form['min_num1']
num2 = request.form['min_num2']
minus = int(num1) - int(num2)
return render_template('index.html', add = add, minus = minus)
Well here is a simple trick
Assume you Have
Form1, Form2, and index
Form1 <form method="post" action="{{ url_for('index',formid=1) }}">
Form2 <form method="post" action="{{ url_for('index',formid=2) }}">
Now In index
#bp.route('/index', methods=['GET', 'POST'])
def index():
formid = request.args.get('formid', 1, type=int)
if formremote.validate_on_submit() and formid== 1:
return "Form One"
if form.validate_on_submit() and formid== 2:
return "Form Two"
I normally use a hidden tag that works as an identifier.
Here is an example:
class Form1(Form):
identifier = StringField()
name = StringField('name')
submit = SubmitField('submit')
class Form2(Form):
identifier = StringField()
name = StringField('name')
submit = SubmitField('submit')
Then you can add a filter in view.py:
....
form1 = Form1()
form2 = Form2()
....
if form1.identifier.data == 'FORM1' and form1.validate_on_submit():
....
if form2.identifier.data == 'FORM2' and form2.validate_on_submit():
....
and finally in the HTML:
<form method="POST">
{{ form1.indentifier(hidden=True, value='FORM1') }}
</form>
<form method="POST">
{{ form2.indentifier(hidden=True, value='FORM2') }}
</form>
If you do it like this in the if statement it will check what was the identifier and if its equal it will run the form stuff you have in your code.
Example: Multiple WTForm in single html page
app.py
"""
Purpose Create multiple form on single html page.
Here we are having tow forms first is Employee_Info and CompanyDetails
"""
from flask import Flask, render_template, request
from flask_wtf import FlaskForm
from wtforms import StringField, IntegerField, FloatField, validators
from wtforms.validators import InputRequired
app = Flask(__name__)
app.config['SECRET_KEY'] = 'Thisisasecret'
class EmployeeInfo(FlaskForm):
"""
EmployeeInfo class will have Name,Dept
"""
fullName = StringField('Full Name',[validators.InputRequired()])
dept = StringField('Department',[validators.InputRequired()])
class CompanyDetails(FlaskForm):
"""
CompanyDetails will have yearOfExp.
"""
yearsOfExp = IntegerField('Year of Experiece',[validators.InputRequired()])
#app.route('/', methods = ['GET','POST'] )
def index():
"""
View will render index.html page.
If form is validated then showData.html will load the employee or company data.
"""
companydetails = CompanyDetails()
employeeInfo = EmployeeInfo()
if companydetails.validate_on_submit():
return render_template('showData.html', form = companydetails)
if employeeInfo.validate_on_submit():
return render_template('showData.html', form1 = employeeInfo)
return render_template('index.html',form1 = employeeInfo, form = companydetails)
if __name__ == '__main__':
app.run(debug= True, port =8092)
templates/index.html
<html>
<head>
</head>
<body>
<h4> Company Details </h4>
<form method="POST" action="{{url_for('index')}}">
{{ form.csrf_token }}
{{ form.yearsOfExp.label }} {{ form.yearsOfExp }}
<input type="submit" value="Submit">
</form>
<hr>
<h4> Employee Form </h4>
<form method="POST" action="{{url_for('index')}}" >
{{ form1.csrf_token }}
{{ form1.fullName.label }} {{ form1.fullName }}
{{ form1.dept.label }} {{ form1.dept }}
<input type="submit" value="Submit">
</form>
</body>
</html>
showData.html
<html>
<head>
</head>
<body>
{% if form1 %}
<h2> Employee Details </h2>
{{ form1.fullName.data }}
{{ form1.dept.data }}
{% endif %}
{% if form %}
<h2> Company Details </h2>
{{ form.yearsOfExp.data }}
{% endif %}
</body>
</html>
Related
class FlowerForm(FlaskForm):
cr_score = IntegerField('Credit Score', validators=[DataRequired()])
geo = StringField('Geography', validators=[DataRequired()])
gen = StringField('Gender', validators=[DataRequired()])
age = IntegerField('Age', validators=[DataRequired()])
ten = IntegerField('Tenure', validators=[DataRequired()])
bal = IntegerField('Balance', validators=[DataRequired()])
num = IntegerField('Number Of Products', validators=[DataRequired()])
has_card = IntegerField('Has Credit Card', validators=[DataRequired()])
is_active = IntegerField('Is Active Member', validators=[DataRequired()])
sal = IntegerField('Estimated Salary', validators=[DataRequired()])
submit = SubmitField('Analyze')
#app.route('/', methods=['GET', 'POST'])
def index():
# Create instance of the form.
form = FlowerForm(request.form)
# If the form is valid on submission
if request.method == "POST" and form.validate_on_submit():
# Grab the data from the input on the form.
session["cr_score"] = form.cr_score.data
session["geo"] = form.geo.data
session["gen"] = form.gen.data
session["age"] = form.age.data
session["ten"] = form.ten.data
session["bal"] = form.bal.data
session["num"] = form.num.data
session["has_card"] = form.has_card.data
session["is_active"] = form.is_active.data
session["sal"] = form.sal.data
return redirect(url_for("prediction"))
print(form.errors)
return render_template('home.html', form=form)
#app.route('/prediction')
def prediction():
#Defining content dictionary
content = {}
content["CreditScore"] = int(session["cr_score"])
content["Geography"] = str(session["geo"])
content["Gender"] = str(session["gen"])
content["Age"] = int(session["age"])
content["Tenure"] = int(session["ten"])
content["Balance"] = int(session["bal"])
content["NumOfProducts"] = int(session["num"])
content["HasCrCard"] = int(session["has_card"])
content["IsActiveMember"] = int(session["is_active"])
content["EstimatedSalary"] = int(session["sal"])
results = return_prediction(model = model, scaler = scaler, onehot = ohencoder, lab_enc=labencoder, sample_json = content)
return render_template('prediction.html',results=results)
The form validation does not seem to work here.
I've tried form.valid_on_submit too.
My home.html file and prediction.html file both have form.hidden_tag() in it.
The if statement gets overriden somehow and I end up back on the home page
HTML home.html code:
<h1>Welcome to Customer Retention Prediction</h1>
<h2>Please enter customer details below:</h2>
<form action = "/" method=”POST”>
{# This hidden_tag is a CSRF security feature. #}
{{form.hidden_tag()}}
{{ form.csrf_token }}
{{form.cr_score.label}} {{form.cr_score}}
<br>
{{form.geo.label}} {{form.geo}}
<br>
{{form.gen.label}} {{form.gen}}
<br>
{{form.age.label}} {{form.age}}
<br>
{{form.ten.label}} {{form.ten}}
<br>
{{form.bal.label}} {{form.bal}}
<br>
{{form.num.label}} {{form.num}}
<br>
{{form.has_card.label}}{{form.has_card}}
<br>
{{form.is_active.label}} {{form.is_active}}
<br>
{{form.sal.label}} {{form.sal}}
<br>
{{form.submit()}}
</form>
prediction.html code:
<h1>Thank You.</h1>
{# This hidden_tag is a CSRF security feature. #}
{{form.hidden_tag()}}
<h2>Probability of this customer leaving the bank is: {{results}}</h2>
Have you tried printing the error
After the if statement try print(form.errors) , it should give you error no crsf token.
In html add this where you used form.hidden_tag()
Below it use {{ form.csrf_token }}
[...]
if request.method == "POST" and form.validate():
# Grab the data from the input on the form.
session["cr_score"] = form.cr_score.data
session["geo"] = form.geo.data
session["gen"] = form.gen.data
session["age"] = form.age.data
[....]
print(form.errors)
return render_template('home.html', form=form)
Edit: you are not using action in form tag.
In html file: it should be this
<form action="/" method="POST">
your index function will be:
#app.route('/', methods=['GET', 'POST'])
def index():
# Create instance of the form.
form = FlowerForm(request.form)
# If the form is valid on submission
if request.method == "POST":
print("yoyo")
if form.validate_on_submit():
# Grab the data from the input on the form.
session["cr_score"] = form.cr_score.data
session["geo"] = form.geo.data
session["gen"] = form.gen.data
session["age"] = form.age.data
session["ten"] = form.ten.data
session["bal"] = form.bal.data
session["num"] = form.num.data
session["has_card"] = form.has_card.data
session["is_active"] = form.is_active.data
session["sal"] = form.sal.data
return redirect(url_for("prediction"))
print(form.errors)
return render_template('home.html', form=form)
Your home.html will be:
<h1>Welcome to Customer Retention Prediction</h1>
<h2>Please enter customer details below:</h2>
<form action="/" method="POST">
{# This hidden_tag is a CSRF security feature. #}
{{form.hidden_tag()}}
{{ form.csrf_token }}
{{form.cr_score.label}} {{form.cr_score}}
<br>
{{form.geo.label}} {{form.geo}}
<br>
{{form.gen.label}} {{form.gen}}
<br>
{{form.age.label}} {{form.age}}
<br>
{{form.ten.label}} {{form.ten}}
<br>
{{form.bal.label}} {{form.bal}}
<br>
{{form.num.label}} {{form.num}}
<br>
{{form.has_card.label}}{{form.has_card}}
<br>
{{form.is_active.label}} {{form.is_active}}
<br>
{{form.sal.label}} {{form.sal}}
<br>
{{form.submit()}}
{{form.errors}}
</form>
So I am trying to basically have a check box on an image page which lets me set a boolean field true/false if I want this image to be deemed the "profile image." The problem is that the form field options are not showing up in the template. Any suggestions?
single_image.html
<form method='POST' action="{% url 'set_profile_image' plant_pk=plnt.pk image_pk=img.pk %}">
{% csrf_token %}
<hr>
{{ form.as_p }}
<hr>
<input type="submit" value="Submit">
forms.py
class SetProfileImageForm(forms.ModelForm):
"""A form to set profile image."""
image_main = forms.BooleanField(required=True)
class Meta:
model = Image
fields = ["image_main","image_url",]
views.py
class SingleImageView(DetailView):
""" A view to see a single image."""
template_name = "project/single_image.html"
queryset = Image.objects.all()
def get_context_data(self, **kwargs):
"""Return a dictionary with context data for this template to use."""
# get the default context data:
# this will include the Profile record for this page view
context = super(SingleImageView, self).get_context_data(**kwargs)
img = Image.objects.get(pk=self.kwargs['image_pk'])
plnt = Image.objects.get(pk=self.kwargs['image_pk']).plant
context['img'] = img
context['plnt'] = plnt
form = SetProfileImageForm()
context['set_profile_image'] = form
# return the context dictionary
return context
def get_object(self):
"""Returns the Note Object that should be deleted."""
# read the URL data values into variables
plant_pk = self.kwargs['plant_pk']
image_pk = self.kwargs['image_pk']
# find the StatusMessage object, and return it
return Image.objects.get(pk=image_pk)
def set_profile_image(request, plant_pk, image_pk):
"""A custom view function to set profile image."""
# find the plant for whom we are setting the image
plant = Plant.objects.get(pk=plant_pk)
if request.method == 'POST':
if "cancel" in request.POST:
return redirect('display_plant', pk=plant.pk)
form = SetProfileImageForm(request.POST or None, request.FILES or None)
if form.is_valid():
plant.set_profile_image(image_pk)
return redirect('display_plant', pk=plant.pk)
else:
print("Error: the form was not valid.")
else:
return reverse('gallery', kwargs={'pk':plant.pk})
You are sending the form instance as a set_profile_imgkey in the context.Change it in your HTML or just rename the context key.
...
context['form'] = form
<form method='POST' action="{% url 'set_profile_image' plant_pk=plnt.pk image_pk=img.pk %}">
{% csrf_token %}
<hr>
{{ form.as_p }}
<hr>
<input type="submit" value="Submit">
OR
...
context['set_profile_image'] = form
<form method='POST' action="{% url 'set_profile_image' plant_pk=plnt.pk image_pk=img.pk %}">
{% csrf_token %}
<hr>
{{ set_profile_image.as_p }}
<hr>
<input type="submit" value="Submit">
So I am trying to allow users to edit menu item prices that are in the database currently. The fields will auto-populate data into the page and users will be able to edit that data to change the price. Here is what I have. I have tried and asked many questions, but I am still lost. I have googled a lot and it helped me understand forms a bit, but I'm not able to fix it. Please let me know if you need more info.
Views.py:
def edit_menu(request):
queryset = Product.objects.all()
context = { "object_list": queryset }
if request.method == 'POST':
post=ProductModelForm(request.POST)
if request.POST.get('price') and request.POST.get('name'):
if 'name' == Product.name:
post.name= request.POST.get('name')
post.price= request.POST.get('price')
post.save()
return redirect('Edit Menu Item')
else:
return redirect('Edit Menu Item')
else:
return render(request, 'mis446/edit-menu-item.html', context)
else:
return render(request, 'mis446/edit-menu-item.html', context)
forms.py:
class ProductModelForm(forms.ModelForm):
class Meta:
model = Product
fields = ['name','price'] # specify which field you need to be in the form
HTML:
<title>ACRMS - Edit Menu Price</title>
<div class = "container">
<form action = "" method = 'POST'>
{% csrf_token %}
{% for instance in object_list %}
<input name = "name" value = "{{ instance.name }}"></input>
<input type="number" name="price" value = "{{ instance.price }}"/><br>
{% endfor %}
</select>
<button type ="submit">Submit Changes</button>
</form>
</div>
Urls.py:
url('edit-menu/edit/',views.edit_menu, name='Edit Menu Item'),
models.py:
class Product(models.Model):
name = models.CharField(max_length=100)
price = models.IntegerField()
slug = models.SlugField()
def __str__(self):
return self.name
For your current implementation, you do not need a form. Instead, update the view like this:
# view
def edit_single_menu(request, pk):
if request.method == 'POST':
post=Product.objects.get(pk=pk)
if request.POST.get('price') and request.POST.get('name'):
post.name= request.POST.get('name')
post.price= request.POST.get('price')
post.save()
return redirect('Edit Menu Item')
else:
return redirect('Edit Menu Item')
return render(request, 'mis446/edit-menu-item.html', context)
# url
url('edit-menu/edit/<pk:id>/',views.edit_single_menu, name='edit_single_menu'),
# template (mis446/edit-menu-item.html)
<title>ACRMS - Edit Menu Price</title>
<div class = "container">
{% for instance in object_list %}
<form action = "{% url 'edit_single_menu' instance.pk %}" method = 'POST'>
{% csrf_token %}
<input name = "name" value = "{{ instance.name }}"></input>
<input type="number" name="price" value = "{{ instance.price }}"/><br>
<button type ="submit">Submit Changes</button>
</form>
{% endfor %}
</div>
Here I am sending individual edit to a new separated view named edit_single_menu and store the changes there.
Update
New url is not meant to replace the old one. It is only to assist you to update individual product. So, you need to keep both of the urls. Also, here is an answer based on #brunodesthuilliers's suggestion:
# view
def edit_single_menu(request, pk):
if request.method == 'POST':
post=Product.objects.get(pk=pk)
form = ProductForm(request.POST, instance=post)
if form.is_valid():
form.save()
return redirect('Edit Menu Item')
Also, do some changes on edit_menu view:
def edit_menu(request):
queryset = Product.objects.all()
context = { "object_list": queryset }
return render(request, 'mis446/edit-menu-item.html', context)
And urls should look like this:
from django.urls import include, path
# rest of the code
path('edit-menu/edit/<int:pk>/',views.edit_single_menu, name='edit_single_menu'),
path('edit-menu/edit/',views.edit_menu, name='Edit Menu Item'),
I have to handle two forms in one function:
HTML page
<form name="selectgenderform" method = "POST">
<select name='gender'>
<option>Male</option>
<option>Female</option>
</select>
<input type = 'submit' name ='searchbtn' value= 'search' >
</form>
<form name="selectionform" method = "POST">
<input type = 'hidden' name = 'valueofnumber' >
<input type = 'submit' name = 'searchbtn' value= 'search' >
</form>
Views.py
def formselection(request):
if selectgenderform in request.POST:
gender = request.POST.get('gender')
...
elif selectionform in request.POST:
value = request.POST.get('valueofnumber')
My query is to handle multiple forms in one function but this will not according to my demand
if you want to keep the two separate forms:
if request.method == "POST" and "selectgenderform" in request.POST:
*something*
if request.method == "POST" and "selectionform" in request.POST:
*something*
you might also have to change the submit input names to "selectgenderform" and "selectionform"
You can pass multiple forms and handle it using single function. However the trick is to keep the forms under one form tag in template. (Bear with me as I am typing on my phone)
views.py
def yourView(request):
form1 = form1()
form2 = form2()
if request.method == "post":
form1 = form1(request.POST)
form2 = form2(request.POST)
if form1.is_valid():
#do something
if form2.is_valid():
#do something else
contest = { "form1": form1, "form2": form2 }
return render(request, 'template.html', context=context)
template.html
<form method="POST">
{%csrf_token%}
{{form1.as_p}}
{{form2.as_p}}
<button type="submit"> Submit </button>
</form>
I have the following stripped function.
def jobs(request):
pms = PM.objects.all()
a = Job.objects.all().filter(enddate__gte=datetime.date.today()).order_by('enddate')
ljform = LaunchJobForm(request.POST or None)
form = LimitedJobForm(request.POST or None, prefix='add')
if request.method=='POST' and 'addjobbtn' in request.POST:
if form.is_valid():
...do stuff...
elif request.method=='POST' and 'launchjobbtn' in request.POST:
print('test')
... do other stuff...
My ljform is
<form method='POST' action = '' class='launchjob'>{% csrf_token %}
{{ ljform }}
<td><button class = 'btn btn-primary' name='launchjobbtn' type='submit'>Launch Job</button></td>
<td><input id='emailcheck' type="checkbox">Modify Email</input></td>
</form>
My addjob form is:
<div class='jobfrm{% if form.errors %} has_errors{% endif %}'>
<span class='closex' >✖</span>
<form method='POST' action = '' class='addjob'>{% csrf_token %}
{{form|crispy}}
<input class = 'btn btn-default' name='addjobbtn' type = 'submit' value = 'Submit'/>
</form>
</div>
My problem is that when I click the launch job button form validation errors are triggered on the jobfrm. It doesn't actually take that if path. It does take the elif path and prints 'test'. But I cannot figure out why it's triggering the other form.
You only want to pass request.POST as an argument to your form if that is the form that has been submitted. This means you have to do something like this:
def jobs(request):
pms = PM.objects.all()
a = Job.objects.all().filter(enddate__gte=datetime.date.today()).order_by('enddate')
ljform = LaunchJobForm()
form = LimitedJobForm()
if request.method=='POST' and 'addjobbtn' in request.POST:
form = LimitedJobForm(request.POST)
if form.is_valid():
...do stuff...
elif request.method=='POST' and 'launchjobbtn' in request.POST:
ljform = LaunchJobForm(request.POST)
print('test')
... do other stuff...