Flask-WTForms auto-submit onchange with macro not working - python

I would like my form to automatically submit once the last field detects an input. Here is what I have on the HTML side based on what I could find online...I know I'm probably missing something...
{% extends "base.html" %}
{% from 'bootstrap/form.html' import render_field %}
{% block content %}
<img src="/static/logo.jpg" alt="logo" width="50%" height="auto">
<h1>Scan ABC...</h1>
<form action="" method="post" novalidate>
{{ form.hidden_tag() }}
<p>
{{ form.A.label }}<br>
{{ form.A(autofocus=true, required=true, size=32) }}
</p>
<p>
{{ form.B.label }}<br>
{{ form.B(required=true, size=32) }}
</p>
<p>
{{ form.C.label }}<br>
{% macro render_field(C(**{required=true, size=32, onchange="this.form.submit()"})) %}
{% endmacro %}
</p>
<p>{{ form.submit() }}</p>
</form>
{% endblock %}
Here is my form.py
from flask_wtf import FlaskForm
from wtforms import StringField, IntegerField, SubmitField
from wtforms.validators import DataRequired
class Form(FlaskForm):
A= StringField('A', validators=[DataRequired()])
B= StringField('B', validators=[DataRequired()])
C= IntegerField('C', validators=[DataRequired()])
submit = SubmitField('Submit')
I get this error
jinja2.exceptions.TemplateSyntaxError: expected token ',', got '('
on this line
{% macro render_field(weight(**{required=true, size=32, onchange="this.form.submit()"})) %}

Does it work in other cases without auto-submit? In my case, I only use onchange="submit()", i.e.for example:
{{ filterform.search_text(class="form-control-button", onchange="submit()") }}
which leads to:
<input checked class="form-control-button" id="search_keywords" name="search_keywords" onchange="submit()" type="checkbox" value="y">
Maybe you want to try onchange="submit()"?

Related

Error message if I'm using IntegerField for one of the form field

I have an IntegerField in my login Form and it throws me an error of unsuccessful login message on submit. Although when I change IntegerField to StringField it works fine and validates the the login. Is there any way how to get IntegerField also validate on submit.
this is my route code
#app.route("/login", methods=['POST', 'GET'])
def login():
form = LoginForm()
if form.validate_on_submit():
if form.username.data == 'User' and form.code.data == '1234':
flash(f'Book your time {form.username.data}', 'secondary')
return redirect(url_for('booking'))
else:
flash('Login Unsuccessful. Please check your name and the code', 'danger')
return render_template('login.html', title='Login', form=form)
this is my forms.py file
from flask_wtf import FlaskForm
from wtforms import StringField, IntegerField, SubmitField
from wtforms.validators import DataRequired, Length, NumberRange
class LoginForm(FlaskForm):
username = StringField('Name', validators=[DataRequired(), Length(min=2, max=20)])
code = IntegerField('Code', validators=[DataRequired(), NumberRange(min=1, max=9999)])
submit = SubmitField('Book time')
this is my login.html file
<main class="form-signin">
<form method="POST" action="">
{{ form.hidden_tag() }}
<img class="mb-4" src="{{ url_for ('static', filename='img/vertical.png') }}" alt="" width="100">
<div class="form-floating">
{{ form.username.label(class="form-lable") }}
{% if form.username.errors %}
{{ form.username(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.username.errors %}
<span>
{{ error }}
</span>
{% endfor %}
</div>
{% else %}
{{ form.username(class="form-control") }}
{% endif %}
</div>
<div class="form-floating">
{{ form.code.label(class="form-lable") }}
{% if form.code.errors %}
{{ form.code(class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in form.code.errors %}
<span>
{{ error }}
</span>
{% endfor %}
</div>
{% else %}
{{ form.code(class="form-control") }}
{% endif %}
</div>
<div class="form-floating">
{{ form.submit(class="w-100 btn btn-lg btn-primary") }}
</div>
<div class="bottom_link">
<a class="link-primary" href="{{url_for('booking')}}">See available bookings</a>
</div>
</form>
</main>

WTForms - Unable to locate the error message reported in the source code

I am working on the Flask tutorial from Miguel for input validation with WTForms. The forms.py is defined below:
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import InputRequired
class LoginForm(FlaskForm):
username = StringField('Username',validators=[InputRequired()])
password = PasswordField('Password',validators=[InputRequired()])
remember_me = BooleanField('Remember Me')
submit = SubmitField('Sign In')
HTML file as below:
{% extends "base.html" %}
{% block content %}
<h1>Sign In</h1>
<form action="" method="post">
{{ form.hidden_tag() }}
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }}<br>
{% for error in form.username.process_errors %}
<span style="color:red;">[{{error}}]</span>
{% endfor %}
</p>
<p>
{{ form.password.label }}<br>
{{ form.password(size=32) }}
{% for error in form.password.process_errors %}
<span style="color:red;">[{{error}}]</span>
{% endfor %}
</p>
<p>{{ form.remember_me() }} {{ form.remember_me.label }}</p>
<p>{{ form.submit() }}</p>
</form>
{% endblock %}
What I tried to achieve is to have the form report missing username and password input with error messages in red color. However, I got the following result when I click "submit"
I couldn't find where in the WTForms package produce the error message "Please fill out this field". I also checked the result HTML page, there is no Javascript code generated for this.
I have tried in both Opera and Edge and got the same error message. Is that something from Windows?
Thanks in advance for your help

Python, Django: Editing inlineformset_factory

inside my app I'm using an inlineformset_factory and right know it's working fine! But when displaying it inside my template the labels are always staying right above the input-field. Is there any way to display them side-by-side or even move the label as some sort of placeholder inside the input-field?
views.py
formset = inlineformset_factory(Model_A, Model_B, can_delete=False, extra=0, fields=('fields_01', 'fields_02', 'fields_03'))
template.html
<form method="post">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{ form }}
{% endfor %}
<button type="submit">Save</button>
</form>
Thanks for all your help and have a great weekend!
Try this:
<form action="" method="POST">
{% csrf_token %}
{{ form.management_form }}
{% for field in form %}
{{field.product.label}} - {{field.product}} #here product is my field name
<hr>
{% endfor %}
<input type="submit" name="Submit">
</form>
You have to do this for every field
#Changes
<form method="post">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{ form.Field_name.label }} - {{form.Field_name}} #1st field
{{ form.Field_name.label }} - {{form.Field_name}} #2nd field
{% endfor %}
<button type="submit">Save</button>
</form>
I think the displaying was influenced by css。
Use F12 to check css in chrome to find the reason。
You can edit the css to change the displaying.
Or use django-widgets-improved and bootstrap to set class to the fields of form.
{% load widget_tweaks %}
<form method="post">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{% for field in form %}
{% render_field field class="form-control" %}
{% endfor %}
{% endfor %}
<button type="submit">Save</button>
</form>

Flask: miss some blocks

I try to write simple service with flask but I have some problem. I try to render a template after submitting, but It doesn't go to some blocks
Main code
#app.route('/', methods=['GET', 'POST'])
def main_page():
main_form = Main_Submit_Form()
text_form = Checking_Text_Form()
image_form = Checking_Image_Form()
if main_form.validate_on_submit():
if main_form.name_checking.data:
if text_form.validate_on_submit():
request_name = str(text_form.checking_name.data)
results = model.predict_name(request_name)
return render_template('text_data.html', request_name=request_name, results=results)
return render_template('login.html', title='Sign In', form=text_form)
if main_form.image_checking.data:
if image_form.validate_on_submit():
pass
return render_template('main.html', form=main_form)
Main form looks like
from flask_wtf import FlaskForm
from wtforms import SubmitField
class Main_Submit_Form(FlaskForm):
name_checking = SubmitField(label='Проверка Торгового наименования')
image_checking = SubmitField(label='Проверка Логотипа')
Text form looks like
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, FileField
from wtforms.validators import DataRequired
class Checking_Text_Form(FlaskForm):
checking_name = StringField('Введите наименование компании', validators=[DataRequired()])
submit_text = SubmitField('Проверить')
Main html
{% extends "base.html" %}
{% block content %}
<h2>Проверка товарного знака</h2>
<form action="" method="post" novalidate>
{{ form.hidden_tag() }}
<p class="text">{{ form.name_checking() }}</p>
<p class="image">{{ form.image_checking() }}</p>
</form>
{% endblock %}
Login html
{% extends "base.html" %}
{% block content %}
<h2>Проверка товарного знака</h2>
<form action="" method="post" novalidate>
{{ form.hidden_tag() }}
<p>
{{ form.checking_name.label }}<br>
{{ form.checking_name(size=32) }}
</p>
<p>{{ form.submit_text() }}</p>
</form>
{% endblock %}
Textdata html
{% extends "base.html" %}
{% block content %}
<h2>Результаты по запросу: {{ request_name }}</h2>
{% for result in results %}
<div><p>{{ result.company_name }}, сходство: <b>{{ result.cosine_sim }}</b></p></div>
{% endfor %}
{% endblock %}
I can't go into block with checking if text_from.validate_on_submit() and I can't understand why.
How can I go into this block after rendering login.html template?
And is any way simplify this code? I don't think that it's a good example

How to improve Django form errors?

If I have a django form, where I want it to provide a bootstrap error input (<input type="text" id="inputError">) to show an error instead of the bullet-list {{ form.title.error }}, how would I go about doing this? Right now I have:
{% if UF.title.errors %}
{{ UF.title }}
{{ UF.title.errors.as_text }}
{% else %}
{{ UF.title }}
{% endif %}
but instead of having UF.title in the first error, I would rather have UF.title but with the ERROR> how would I go about doing this?
You should use django-bootstrap3.
It does exactly what you want.
{% load bootstrap3 %}
{# Display a form #}
<form action="/url/to/submit/" method="post" class="form">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button type="submit" class="btn btn-primary">
{% bootstrap_icon "star" %} Submit
</button>
{% endbuttons %}
</form>
Here's what I do for my code:
<div class="form-group {% if form.username.errors %}has-error{% endif %}">
{{ form.username }}
{% if form.username.errors %}
<span class="help-block">{{ form.username.errors.0 }}</span>
{% endif %}
</div>
And my forms.py looks like:
from django import forms
class LoginForm(forms.Form):
username = forms.CharField(label='Username', max_length=32, widget=forms.TextInput(attrs={'placeholder': 'Username', 'class': 'form-control'}))

Categories