Use field label as placeholder with django-widget-tweaks - django

I am using django-widget-tweaks and unable to figure out how to add a field variable as placeholder, like the following:
<div class="col-sm-10">
{{ field|append_attr:"class:form-control"|append_attr:"placeholder:field.label" }}
{% if field.help_text %}
<p class="help-block"><small>{{ field.help_text }}</small></p>
{% endif %}
</div>
field.label above does not evaluate and puts the string "field.label" as the placeholder on the page.
Some SO posts suggest registering a custom tag/filter which seems complicated for something this simple.

I am now using render_field to render the field instead of using template filters and it seems to work.
<div class="col-sm-10">
{% render_field field class="form-control" placeholder=field.label %}
{% if field.help_text %}
<p class="help-block"><small>{{ field.help_text }}</small></p>
{% endif %}
</div>
It seems form variables cannot be used within template filters and can only be used with render_field (though the django-widget-tweaks documentation doesnt say that explicitly).

Related

Show / hide input field or div based on RadioField choice using Flask wtf_form

I am trying to build website using Flask, and can't find solution to one problem. I am trying to hide or show input field, based on RadioFeild choice. Also, if input field showing, it have to be required. I actually have everything working, besides knowing what RadioField choice was selected. I can see the form when loading page on 127.0.0.1:5000 and I can see RadioField with 2 choices: Yes and No, but when I click on yes, there are no changes, hidden input field is still not showing. Please, help!
app.py
class MyClass(FlaskForm):
my_field = RadioField("bla-bla-bla", choices=[('Yes', 'Yes'), ('No', 'No')], validators [InputRequired()])
#app.route("/some_page")
def some_page():
form = MyClass()
return render_template("some_page.html", form=form)
_render_field.html
{% macro render_radio_field(field) %}
<div class="form__item">
<label class="form__label">{{field.label.text }}</label>
<div class="form-group">
{{ field(class_='form__input', **kwargs)|safe }}
{% for subfield in field %}
<div class="form__item">
<label>
{{ subfield }}
{{ subfield.label.text }}
</label>
</div>
{% endfor %}
</div>
</div>
{% endmacro %}
some_page.html
{% from "_render_field.html" import render_field, render_radio_field %}
{% extends "layout.html" %}
{% block title %}My Title{% endblock %}
{% block content %}
<div style="width:600px; margin:0 auto;">
<h3>Some Text</h3>
<form class="form" action="{{url_for('some_page')}}" method="POST">
{% from "_render_field.html" import render_field, render_radio_field %}
{{ form.csrf_token }}
{{ render_field(my_field, title="", style="list-style:none") }}
{% if form.my_field.option == "Yes" %}
{{ render_field(form.some_other_StringField, placeholder="Please explain:", title="") }}
{% endif %}
<input type="submit" name="" value="login" class="form__btn">
</form>
</div>
{% endblock %}

How to exclude specific field types in a template form loop

I am using django_widget_tweaks to loop over form fields:
{% for field in form.visible_fields %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{% 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 %}
This displays a happy Bootstrap4 compliant interface, except when displaying fields like radio when I need to use a custom-control class not the form-control class.
How can I filter the form field loop to exclude radio inputs so I can write this code separately?
I need to understand how to filter the field loop and what the correct way to do this with the field type for radio is.

Error handling for checked fields Django multiselectfield

I have a conditional check where I need to look at a certain checkbox, and depending on that, a multiselect field becomes required.
I have something similar in place:
{% for value, text in form.customfield.field.choices %}
<div class="checkbox custom-control custom-checkbox list-inline-item" style="display:inline-flex;">
<input type="checkbox" name="{{customfield.name}}" value="{{value}}" class="list-inline-item custom-control-input" title="" id="id_{{value}}" {% if value in customfield.data %} checked="checked"{% endif %}>
<label for="id_{{value}}" class="form-check-label custom-control-label mr-3">{{text}}</label>
</div>
{% endfor %}
Is there a way to do error handling for this? I verified that my form.is_valid() returns false, but the error message does not get displayed, like it does for inputs/textboxes. I'm assuming I need to print the specific error out in the template explicitly, as I am not using defaults like {{ form.customfield }} or {{ bootstrap_field }}
form.is_valid() returns False.
form._errors gives me:
<ul class="errorlist"><li>customfield<ul class="errorlist"><li>This field is required when the other field is checked.</li></ul>
Rant: As with many other Django questions I've asked, I had to post my own answer. End Rant!
Along with the above check, just loop through the field.errors and display the error
Note: invalid-feedback is used to hide/display the error message in Bootstrap4, so
<div id="id_{{customfield.name}}" class="list-inline-item {% if customfield.errors %} is-invalid{% endif %}">
{% for value, text in form.customfield.field.choices %}
<div class="checkbox custom-control custom-checkbox list-inline-item">
<input type="checkbox" name="{{customfield.name}}" value="{{value}}" class="list-inline-item custom-control-input" title="" id="id_{{value}}" {% if value in customfield.data %} checked="checked"{% endif %}>
<label for="id_{{value}}" class="form-check-label custom-control-label">{{text}}</label>
</div>
{% endfor %}
</div>
{% if customfield.errors %}
<div class="invalid-feedback">
{% for error in customfield.errors %} {{ error }} {% endfor %}
</div>
{% endif %}

Django selectdatewidget how to render manually?

I'm trying to render a selectdatewidget in django out manually so I can customise with bootstrap. However I'm not clear on how I render out the indvidual inputs with the selectdatewidget?
class ProfileForm(forms.Form):
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
eighteen_years_from_now = (datetime.datetime.now().year - 18)
date_of_birth = FieldBuilder(User, 'date_of_birth', widget=SelectDateWidget(
years=range(eighteen_years_from_now, 1919, -1)))
template to render an individual field:
<div class="form-group">
<label for="{{ field.id_for_label }}" class="sr-only">
{{ field.label }}
</label>
{% 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" placeholder=field.label %}
{% endif %}
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text }}</small>
{% endif %}
</div>
The short answer is that you can't get the control needed, without overriding the inbuilt django template.
Thankfully Django 1.11 changed the widget system to use templates rather than python code making this easier to override.
From reviewing the templates in django/forms/templates/django/forms/widgets we can see that the select date widget loads the multiwidget template which for each subwidget loads the widget template:
{% for widget in widget.subwidgets %}{% include widget.template_name %}{% endfor %}
For select date widget this means the output is the 3 select tags (month, day, year) next to each other. This can't be eg made inline with bootstrap as each <select> needs to be wrapped in a div with the appropriate css class.
Templates can be overriden by following the django docs here:
https://docs.djangoproject.com/en/1.11/ref/forms/renderers/#overriding-built-in-widget-templates

django admin get verbose name in template

I'm overriding the django admin/templates/admin/includes/fieldset.html
I want my checkbox labels to be wrapped around the checkbox, but I can't figure out a way to access the verbose name of the model. Normally I would just add a method to the model but since I'm doing this in the admin and want to do it for every model, everywhere without effort I was wondering if here was an easier way.
This is what I have so far:
{% if field.is_checkbox %}
<div class="checkbox">
<label for="{{ field.auto_id }}" class="vCheckboxLabel">
{{ field.field }}
{{ field.give_me_the_verbose_name_for_the_model_plsthx }}
</label>
{% if field.field.help_text %}
<p class="help-block">{{ field.field.help_text|safe }}</p>
{% endif %}
</div>
{% else %}
...
You can access verbose name by:
field._meta.verbose_name
But it works only in view, you haven't _meta in template.