Populate textarea field using WTForms - python

As I understand it, if you want to populate a textarea you place the text between the textarea tags. However I am using WTForms. How can I pre-populate the form from views or in my template?
FORM
class ModuleSectionForm(FlaskForm):
title = StringField('Section Title', validators=[DataRequired()])
description = TextAreaField('Description', validators=[DataRequired()])
submit = SubmitField('Add Section')
VIEW
#modules.route('/update_section/<name>/<title>', methods=['GET', 'POST'])
def update_section(name, title):
form = ModuleSectionForm()
module = Module.objects(title=name).first()
section = None
for sect in module.sections:
if sect.title == title:
section = sect
#if form.validate_on_submit():
#save data
return render_template('modules/update_section.html', section=section, form=form)
TEMPLATE
<form method="post" action="{{ url_for('modules.update_section', name=name) }}">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.title.label(class="form-control-label") }}
{{ form.title(class="form-control", value=section.title) }}
</div>
<div class="form-group">
{{ form.description.label(class="form-control-label") }}
{{ form.description(class="form-control", default=section.description) }}
</div>
<div class="form-group">
{{ form.submit(class="btn btn-secondary shadow") }}
</div>
</form>

This can be done by just assigning the text to display beforehand (in the view, for instance).
Try edit your view (update_section) this way:
+ form.description.data = 'text you want to display'
And your template as follows:
- {{ form.description(class="form-control", default=section.description) }}
+ {{ form.description(class="form-control") }}
Mind you, there's an alternative way, which is to specify the placeholder attribute (but I guess is not what you want to do here).

Typically with WTForms (let's assume you're using Flask and Bootstrap here), you'll use the value attribute of the input to pre-populate a form field. Note that pre-populating a field is distinct from providing a 'placeholder', which is just an ephemeral hint. So usually we pre-populate like this:
<div class="form-group row">
<label for="form_subject" class="col-sm-2 col-form-label">Subject</label>
<div class="col-sm-7">
<input class="form-control" id="form_framework" name="form_framework"
value="{{ instruct.Subject }}">
</div>
</div>
With Flask and Bootstrap, the name attribute is required to pass the value back to the Controller upon submission, the value attribute is used to pre-populate the field from the object - in this case, our controller has passed in an object called instruct, which has an attribute Subject.
But you have to be aware that different kinds of inputs in WTForms have different attributes, and this is left as a fun challenge for the developer to figure out.
TextArea doesn't have a value attribute, so in order to pre-populate the field, you have to provide the value between the tags, like so (again, using Bootstrap here in case any of these tags are unfamiliar):
<div class="form-group row">
<label for="form_longish_text"
class="col-sm-2 col-form-label">Longish Text</label>
<div class="col-sm-7">
<textarea class="form-control" rows="3"
id="form_longish_text"
name="form_longish_text">{{ instruct.LongishText }}
</textarea>
</div>
</div>

Related

Get the details of selected item

I have a part table and delivery instruction table (dins). To create a dins, I have to choose a part name. So what I want to do is, after choosing the part name from the dropdown that part's price will be visible in the form.
In the Part table, I have the price value for the specific part name. So during the creation of dins, after choosing such an example part name is X, then the form should show what is the price of that chosen part (X part) price.
Any idea how to make that happen?
views.py
def create_deliveryins(request):
from django import forms
form = DeliveryInsForm()
if request.method == 'POST':
forms = DeliveryInsForm(request.POST)
if forms.is_valid():
product = forms.cleaned_data['product']
usage = forms.cleaned_data['usage']
part= forms.cleaned_data['part']
deliveryins = DeliveryIns.objects.create(
usage=usage,
product=product,
part=part,
)
return redirect('dins-list')
context = {
'form': form
}
return render(request, 'store/addDins.html', context)
HTML
<form action="#" method="post" novalidate="novalidate">
{% csrf_token %}
<div class="form-group">
<label for="product" class="control-label mb-1">Product</label>
{{ form.product }}
</div>
<div class="form-group">
<label for="part" class="control-label mb-1">Part</label>
{{ form.part}}
</div>
<div class="form-group">
<label for="usage" class="control-label mb-1">Usage</label>
{{ form.usage }}
</div>
</form>
Create a hidden form field that has the part prices for each part.
Use Javascript or Jquery to update the form field for price and show it whenever the form part field is changed.
This would prevent the need for ajax, or additional views or requests.
You would only need to slightly modify your view and template.

Updating user profile - Django

I've created a template for updating account profiles using a Bootstrap snippet (from https://www.bootdey.com). With the django default format (like {{ form.as_p }}), updating accounts works (for example, when I modify the first name, it changes in the database). When I use the bootstrapp snippet, it doesn't update: it goes straight to 'homepage' without updating (as explained in views.py).
In forms.py
class EditAccountForm(UserChangeForm):
class Meta:
model = Account
fields = ('email','first_name','last_name')
In views.py
def EditProfile(request):
context= {}
if request.POST:
form = EditAccountForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
email = form.cleaned_data.get("email")
raw_password = form.cleaned_data.get("password1")
account = authenticate(email=email,password=raw_password)
return redirect('profile_page')
else:
context['edit_form'] = form
return redirect('homepage')
else:
form = EditAccountForm(instance=request.user)
context['edit_form'] = form
return render(request,'Account/edit_page.html',context)
the template: edit_profile.html (I only show the first_name part as example)
<form method = "POST" class="form" novalidate="">
{% csrf_token %}
<div class="row">
<div class="col">
<div class="row">
<div class="col">
<div class="form-group">
<label>First name</label>
<input class="form-control" type="text" name="firstna" value={{ edit_form.first_name.value }}>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col d-flex justify-content-end">
<button class="btn btn-primary" type="submit">Save Changes</button>
PS: I've preferred to use those snippets instead of the Django style since I find them more attractive and offer more freedom.
Please check you are taking same value if you are changing the data in views like if you are using (name="firstna") in template so for First Name you have to take same in views.
Same question is asked here you can go and follow below link
[How to update user profile in Django

Message not flashing on some WTForm validation methods

This question is related to this question, but focussing on one of the underlying issues I didn't know about when asking that other question.
I'm using Python, Flask and WTForms to make a form. Here's the python:
from flask import render_template
from flask_wtf import FlaskForm
from wtforms import DecimalField, SubmitField
from wtforms.validators import NumberRange, DataRequired
class NumberForm(FlaskForm):
question_one = DecimalField('Question 1', validators=[NumberRange(min=0, max=10)])
question_two = DecimalField('Question 2', validators=[DataRequired()])
submit = SubmitField('Submit')
#app.route('some_route/', methods=['GET', 'POST'])
def page():
form = NumberForm()
if form.validate_on_submit():
return some_success_or_other
return render_template('page.html', form=form)
And the HTML:
<form method="POST">
<div class="form-group-row">
{{ form.hidden_tag() }}
{{ form.question_one.label }}
<div>
{{ form.question_one }}
</div>
</div>
<div class="form-group-row">
{{ form.question_two.label }}
<div>
{{ form.question_two }}
</div>
</div>
<div class="form-group-row">
{{ form.submit }}
</div>
</form>
The two validators I'm using (NumberRange and DataRequired) behave differently. When data isn't entered in field 2 and the submit button is clicked, the form isn't submitted and an error message pops up next to the field saying "Please fill in this field".
When strings (rather than decimals), or numbers outside the range is submitted in field 1, the form does submit when the button is pressed.
Although the error is logged (and can be shown using {{ form.errors }}, I wanted the same behaviour for both validators - I'd like the form to be prevented from submitting when invalid numbers/strings are entered in field 1.
Anyone know why the validators behave differently?
HTML5 introduces the required attribute which makes it mandatory to fill a field and block form validation if one of the fields (affected by this attribute) has not been populated; this attribute is only available for the input tag.
With flask-wtf, when you use a field with the required validator, it will automatically generate a html field with the required attribute, which will block the form from being sent and display an infobule.
In the case of other validators such as NumberRange, it is not the same.
With pure HTML:
to have the same behavior, ie to check that the number entered is in a well-defined range and to block the sending of the form if it is not the case, it is necessary to use the pattern attribute (more details here). There is no predefined pattern for this particular case, so you will need to create a custom pattern using regular expressions. It will give this: <input type="text" pattern="[0-9]">.
Now we just have to reattake the same logic with wtforms...
With wtforms:
<form method="POST">
<div class="form-group-row">
{{ form.hidden_tag() }}
{{ form.question_one.label }}
<div>
{{ form.question_one(pattern="[0-9]") }}
</div>
</div>
<div class="form-group-row">
{{ form.question_two.label }}
<div>
{{ form.question_two }}
</div>
</div>
<div class="form-group-row">
{{ form.submit }}
</div>
</form>
At line {{ form.question_one(pattern="[0-9]") }}, I use the pattern attribute with a regular expression that checks that the number entered is in the range 0 to 9. For larger ranges, you will need to write regular expressions a little more complex (this link is interresting)

Flask wtf-form override error message

Im using wtf-form for my password reset page but im having trouble with the generated error messages. I want to be able to either disable the error that wtf-form generates and use my own or be able to override them.
{% for e in form.password.errors %}
<span class="label label-danger">{{ e }}</span>
{% endfor %}
<form action="http://127.0.0.1:5000/setpassword" method=post>
<div class="form-group">
{{ form.csrf_token }}
{{ wtf.form_field(form.password, class='form-control', placeholder='Enter Password') }}
</div>
class PasswordForm(FlaskForm):
password = PasswordField('',validators=[pass_num, pass_small_lett, pass_big_lett, pass_special, pass_min])
confirm = PasswordField('',[validators.EqualTo('password', message='Not matching')])
submit = SubmitField('Send')
Don't use form_field() if you don't want its extra functionality. This will render just the input field:
{{ form.password(class='form-control', placeholder='Enter Password') }}
In your example the field's label is empty, but in case the field has a label, it must be printed as well. Bootstrap rules are:
Wrap labels and form controls in <div class="form-group"> (needed for optimum spacing)
Add class .form-control to all textual <input>, <textarea>, and <select elements
(source: https://www.w3schools.com/bootstrap/bootstrap_forms.asp)

Flask - Jinja 2 template - rendering a bootstrap list select box

My web app created by Flask is using Jinja 2 template. I created my form from the request form value as below:
form = T3InputForm(request.form)
And defined my T3InputForm as:
class T3InputForm(Form):
savgp = StringField('Selected Averaging Period',
validators=[DataRequired()])
In my HTML file, I have
<div class="form-group col-md-6">
<p> <h4>{{ form.savgp.label}} : {{ form.savgp }} </h4></p>
</div>
So I can assign my input to the {{ form.savgp }} variable and pass it to my python function. Now, My question is that, How can I render a bootstrap list select box and assign the value of that to the form.savgp variable using Jinja 2 template:
To render a list select box using bootstrap I know this is the code lines:
<select class="form-control">
<option value="one">One</option>
<option value="two">Two</option>
<option value="three">Three</option>
<option value="four">Four</option>
<option value="five">Five</option>
</select>
How should assign those options for the {{ form.savgp }} variable?
Please let me know if I can provide any further information to explain my issue better.
I think its helpful to you
forms.py
class T3InputForm(Form):
savgp = SelectField('Selected Averaging Period', choices=[('one', "One"), ('two, "Two"),('three', "Three"), ('four, "Four"),('five',"Five")], [validators.Required()])
html
<div class="form-group col-md-6">
<p> <h4>{{ form.savgp.label}} : {{ form.savgp(class_="form-control") }} </h4></p>
</div>

Categories

Resources