RadioField never validates correctly - html

I'm new to flask and try to build a simple demographics survey. While validating a StringField (e.g. Nationality) works fine, I have trouble with the RadioField. No error messages occur if I don't provide any input for the RadioField. I think the problem lies in my jinja2 template but I'm not able to find what I'm doing wrong.
Any suggestions?
extract from main.py:
class DemographicsForm(FlaskForm):
Gender = RadioField(
'Gender',
choices=[('M', 'Male'), ('F', 'Female'), ('O', 'Other')],
validators=[InputRequired()]
)
#app.route("/demographics", methods=['GET', 'POST'])
def demographics():
form = DemographicsForm()
return render_template('demographics.html', title='Demographic Information', form=form)
extract from demographics.html:
<div class="form-group">
{{ form.Gender.label(class='radio') }}
{% if form.Gender.errors %}
{{ form.Gender(class='radio is-invalid') }}
<div class="invalid-feedback">
{% for error in form.Gender.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.Gender(class='radio') }}
{% endif %}
</div>

Actually the problem comes from your Jinja code. The way you implemented error handling is pretty confusing. It should be as simple as this one:
<div class="form-group">
{{ form.Gender.label(class='radio') }}
{{ form.Gender(class='radio') }}
{% for error in form.Gender.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</div>
Thus, when you send the form without having selected a radio button, an error message will appear on your page (in the code above it will appear in red) and in your console.
More details here

Related

How to change default background of checkbox using flask and wtforms?

I don't understand where to add the class name so I can change the background color of the checkbox.
form.py
DOMAINS = ['Bakeries', 'Bars and Pubs', 'Butcher Shops', 'Electronics', 'Fashion', 'Fish Shops',
'Flowers', 'Furniture', 'Gelaterias and Sweets', 'Pets', 'Other', 'Restaurants and Cafés', 'Sport',
'Supermarkets', 'Vegetables and Fruits']
class MultiCheckboxField(SelectMultipleField):
widget = widgets.ListWidget(prefix_label=False)
option_widget = widgets.CheckboxInput()
class BuyerForm(FlaskForm):
address = StringField(label='Address', validators=[InputRequired()])
domains_fields = [(x, x) for x in DOMAINS]
domains = MultiCheckboxField(label='Domains', choices=domains_fields)
radius = DecimalRangeField(label='Radius (KM)', default=5, validators=[InputRequired()])
submit = SubmitField(label='Search')
buyer_form.html
<div class="form-group">
{{ form.domains.label(class="form-control-label") }}
{% if form.domains.errors %}
{{ form.domains(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.domains.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.domains(class="form-control form-control-lg") }}
{% endif %}
</div>
I'm looking where to add:
CSS file
.container input:checked ~ .checkmark {
background-color: #e86875;
}
(I took it from w3school)
First of all, the part of the CSS you've taken from the example code will not work on its own. When you look at the complete example, it actually removes the original checkboxes and replaces them with new ones done entirely in CSS so they can look and behave a certain way. This means you will need to include the entire CSS code to make the checkboxes look like in the example and change color when selected.
Once you have that done, you can put this in your buyer_form.html code:
<div class="form-group">
{{ form.domains.label(class="form-control-label") }}
{% if form.domains.errors %}
{{ form.domains(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.domains.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{% for domain in form.domains %}
<label class="container">{{ domain.label() }}
{{ domain() }}
<span class="checkmark"></span>
</label>
{% endfor %}
{% endif %}
</div>

Why the Django update method throwing error even though I am able to update the user profile successfully.?

I have a Django method written to update user profile. The purpose of the method is solved, as I am able to click on the "update" button and modify the existing data.
Note: I have written method to update Default User model and extended User model(custom fields). Below is the code snippet from views
views.py
#login_required(login_url="/login/")
def editUserProfile(request):
if request.method == "POST":
form = UserProfileUpdateForm(request.POST, instance=request.user) # default user profile update
obj = UserProfile.objects.get(user__id=request.user.id)
form1 = UserProfileForm(request.POST or None, instance=obj)
if form.is_valid() and form1.is_valid():
obj.Photo = form1.cleaned_data['Photo']
obj.dob = form1.cleaned_data['dob']
obj.country = form1.cleaned_data['country']
obj.State = form1.cleaned_data['State']
obj.District = form1.cleaned_data['District']
obj.phone = form1.cleaned_data['phone']
form.save()
form1.save()
messages.success(request, f'updated successfully')
return redirect('/profile1')
else:
messages.error(request, f'Please correct the error below.')
else:
form = UserProfileUpdateForm(instance=request.user)
form1 = UserProfileUpdateForm(instance=request.user)
return render(request, "authenticate\\editProfilePage.html", {'form': form, 'form1': form1})
corresponding HTML code.
editProfilePage.html
{% load static %}
{% block content %}
<h2 class="text-center">Edit Profile</h2>
<form method="POST" action="{% url 'editUserProfile' %}">
{% csrf_token %}
{% if form.errors %}
<div class="alert alert-warning alert-dismissable" role="alert">
<button class="close" data-dismiss="alert">
<small><sup>x</sup></small>
</button>
<p>Form has error..!!</p>
{% for field in form %}
{% if field.errors %}
{{ field.errors }}
{% endif %}
{% endfor %}
</div>
{% endif %}
{{ form.as_p }}
{{ form1.as_p }}
<!-- {{ form1.dob }}-->
<!-- {{ form1.country }}-->
<!-- {{ form1.State }}-->
<!-- {{ form1.District }}-->
<!-- {{ form1.phone }}-->
<input type="submit" value="update" class="btn btn-secondry">
</form>
<br/><br/>
{% endblock %}
If one see in the first glance I do not see any issue immediately as my purpose of updating the profile is successful.
However, to test, after I update a user profile I logout the user which redirects me to login page, and there I see error "Please correct the error below." three times which is coming from the "else" part of the update method. I also see a message "updated successfully" on the same login screen which is coming from the "if" part of the update method as mentioned above(screenshot attached -- update_error3).
So, I have below observations:
My update method "editUserProfile" is somehow calling the inner most "if - else" together.
I think the issue lies in the HTML page. I could say this because when I click on the "update" button from the profile page, I see "email" field appearing twice on the screen and the "update button to insert the data to database(screenshot attached -- update_error1).
Now, I could see the rest of the fields only after I click on the "update" button further(screenshot attached -- update_error2). Furthermore, this is when I enter all my details and when I click on the "update" button, the data get saved successfully in the database and redirected to the profile page with the new data.
Finally, I think the issue is something related to the HTML code. May be I am wrong.
Any thought?
update_error1
The problem is with your messages rendering on the template.Just add this block of code
to your base template that immediately extends your update template.
{% if messages %}
<ul class="messages ">
{% for message in messages %}
<ol class="breadcrumb ">
<li{% if message.tags %} class="{{ message.tags }} " {% endif %}><strong>{{ message }} {{form.errors}}</strong>
</li>
</ol>
{% endfor %}
</ul>
{% endif %}

storage must be a werkzeug.FileStorage(FLASK-UPLOAD)

Hello Everyone,
This is my first time here. I have been having issues regarding the flask_upload to upload the files. I am not sure where I am going wrong with the flask_upload. Hence every time I have been trying to upload the file it is throwing the error in the title
(** storage must be a werkzeug.FileStorage)
enter image description here**)
I am attaching the pictures of my application factory, along with the config file and the html file.Any help will be greatly appreciated.Since I am not sure where I am going wrong
{% block content %}
<h1>upload files</h1>
<form action="{{ url_for('rep.upload') }}" method="post",enctype="multipart/form-data">
{{ form.hidden_tag() }}
<p>
{{ form.report_title.label }}<br>
{{ form.report_title(size=32) }}<br>
{% for error in form.report_title.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.report_description.label }}<br>
{{ form.report_description(size=64) }}<br>
{% for error in form.report_description.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.report_file.name }}<br>
{{ form.report_file}}<br>
{% for error in form.report_file.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>{{ form.submit() }}</p>
</form>
{% endblock %}
enter code here
(Report Blueprint)
#rep.route("/add",methods=['GET','POST'])
#login_required
#roles_requried("patient")
def upload():
form = AddReportForm()
if form.validate_on_submit():
print(request.files.get('report_file'))
filename = images.save(request.files.get('report_file'),name="Hello",folder="static/img",)
url = images.url(filename)
data = {"report_title":form.report_title.data,"report_description":form.report_description.data,
"report_filename":filename,"report_url":url}
print(data)
new_report = Report(**data)
new_report.save()
flash( 'New report, {}, added!'.format(new_report.report_title), 'success')
return redirect(url_for('user.profile'))
return render_template(template_name_or_list='user/add_report.html',form=form)
enter code here
[config.py]
UPLOADS_DEFAULT_DEST = '/static/img/'
UPLOADS_DEFAULT_URL = 'http://localhost:5000/img/'
UPLOADED_IMAGES_DEST = '/static/img/'
UPLOADED_IMAGES_URL = 'http://localhost:5000/img/'
enter code here
(extensions)
images = UploadSet('images',IMAGES)
enter code here
(Application Factory)
app = Flask(__name__, instance_relative_config=False)
app.config.from_object(config_settings)
handler = RotatingFileHandler(app.config.get('LOGGING_LOCATION'), maxBytes=10240,backupCount=10 )
handler.setLevel(app.config.get('LOGGING_LEVEL'))
formatter = handler.setFormatter(app.config.get('LOGGING_FORMAT'))
handler.setFormatter(formatter)
patch_request_class(app, 32 * 1024 * 1024 )
app.register_blueprint(user)
app.register_blueprint(doc)
app.register_blueprint(adm)
app.register_blueprint(rep)
configure_uploads(app, images)
app.logger.addHandler(handler)
error(app)
extensions(app)

how to use django widget tweaks and combine template class string and widget attr attributes string name

I am trying to customise a django form for use with bootstrap 4, custom html layout & per field class or id names on the FormModel defintion
I have the following html
{% for hidden_field in form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
{% if form.non_field_errors %}
<div class="alert alert-danger" role="alert">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
{% for field in form.visible_fields %}
<div class="form-group">
{{ field.label_tag }}
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control is-invalid" %}
{% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control is-valid" %}
{% endif %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text }}</small>
{% endif %}
</div>
{% endfor %}
And the following form defintion:
class DocumentForm(forms.ModelForm):
field1 = PartLookupField(required=True, widget=forms.TextInput(attrs={'class': 'field1-choice-ajax'}))
field2 = forms.CharField(required=True, widget=forms.TextInput(attrs={'id': 'field2-field'}))
form_lines = forms.CharField(widget=forms.HiddenInput())
class Meta:
model = Document
fields = ("field1", "field2", "form_lines")
So essentially, I need to get the per field definition of id or class, from the widget on the model, and combine that with the template defined form-control or is-valid/invalid classes in the template.
I've tried going down this route
How to concatenate strings in django templates?
But it just seems like it's going to end up in a huge mess.
Essentially, how can I combine template defined attributes and per field defined attributes? I need to end up with class="form-control field1-choice-ajax" for the field specified in the model (and the correct extra class names for the valid/invalid states).
Previously I was using the bootstrap4 form library, but I need complete control now:
{% csrf_token %}
{% bootstrap_form form %}
I've created my own template filter in order to add class attributes to existing form fields:
#register.filter
def add_class(field, css):
"""Add a class to a field in a template.
Example:
> {{ form.my_field|add_class:"required" }}
<input id="my_field_id" name="my_field" class="required" type="text">
Args:
field: this should be a form field, of type ``BoundField``
css: this should be a string with one or more class names separated by spaces
"""
class_old = field.field.widget.attrs.get('class', None)
class_new = class_old + ' ' + css if class_old else css
return field.as_widget(attrs={'class': class_new})
So now I can do this in a template:
{{ field|add_class:"is-valid" }}
Use Widget Tweaks.
It allows you to do something like:
{{ field|add_class:'form-control' }}

Python Flask Templeta <br> newline doesnt work

im using python Flask and got this template
{% extends "base.html" %}
{% block content %}
{% for ticket in tickets %}
Ticket: {{ ticket.id }} Subject: {{ ticket.subject }} <br/>
{% endfor %}
{% endblock %}
but <br> and <br/> doesnt work, the Text (<br>) is not displayed and there is no new line.
Anyone an idea?
Thank you
got 2 templates one called ticket.html and one called tickets.html i copied tickets.html to ticket.html but then referenced ticket.html in the route of tickets
Try this:
<div>Ticket: {{ ticket.id }} Subject: {{ ticket.subject }}</div>