How Do I Render Form Attributes Manually in Django? - python

I am trying to render the name attribute manually.
{% for language in form.languages %}
<div class="form-check">
<input class="form-check-input" id="{{ language.id_for_label }}" name="{{ language.field.name }}" type="checkbox">
<label class="form-check-label" for="{{ language.id_for_label }}">{{ language.choice_label }}</label>
</div>
{% endfor %}
Everything gets rendered nicely except the name attribute of the input tag.
form.languages is a ManyToManyField shown on my form as a ModelMultipleChoiceField using the following code in my forms.py.
languages = forms.ModelMultipleChoiceField(
queryset=Language.objects.all(),
widget=forms.CheckboxSelectMultiple
)
EDIT: Found the culprit, apparently I need a value attribute, not a name attribute, now I just need to find a way to get the value into the template.

I fixed the issue. What I did was use {{ language.data.value }}.

Related

get name attr value for formset with appropriate prefix and formset form index

I am manually displaying modelformset_factory values in a Django template using the snippet below. One of the inputs is using the select type and I'm populating the options using another context value passed from the view after making external API calls, so there is no model relationship between the data and the form I'm trying to display.
view
my_form = modelformset_factory(MyModel, MyModelForm, fields=("col1", "col2"), extra=0, min_num=1, can_delete=True,)
template
{{ my_form.management_form }}
{% for form in my_form %}
<label for="{{ form.col1.id_for_label }}">{{ form.col1.label }}</label>
{{ form.col1 }}
<label for="{{ form.col2.id_for_label }}">{{ form.col2.label }}</label>
<select id="{{ form.col2.id_for_label }}" name="{{ form.col2.name }}">
<option disabled selected value> ---- </option>
{% for ctx in other_ctx %}
<option value="{{ ctx.1 }}">{{ ctx.2 }}</option>
{% endfor %}
</select>
{% endfor %}
The other_ctx populating the select option is a List[Tuple]
I am trying to get the name value for the col2 input using {{ form.col2.name }} but only col2 is getting returned instead of form-0-col2. I could prepend the form-0- value to the {{ form.col2.name }} but wondering if:
I could do the above automatically? I'm assuming the formset should be aware of the initial formset names with appropriate formset index coming from the view.
Is there a way to include the select options in the initial formset that is sent to the template so that I can simply use {{ form.col2 }}?
Just saw that I could use form-{{ forloop.counter0 }}-{{ form.col2.name }} as an alternative as well, if getting it automatically does not work.
I think what you are after is form.col2.html_name - docs
This is the name that will be used in the widget’s HTML name attribute. It takes the form prefix into account.

wagtail formbuilder show 'required' in template

I am implementing a Formbuilder form in a wagtail website, but like to get the required value while looping over the form fields so I can show a required icon. The required seems to be in the query, but nothing I try shows me a result.
Create a loop through form
django doc
{% for field in form.visible_fields %}
<div>
<div class="form-group">
{{ field.errors }}
{{ field.label_tag }}
<input type="{{ field.field.widget.input_type }}" class="form-control"
name="{{ field.name }}" id="{{ field.id_for_label }}"
{% if field.field.required %}required="required"{% endif %}>
{% comment %}you might want form field for textarea or select etc. just make conditions for those {% endcomment %}
</div>
</div>
{% endfor %}
Wagtail form builder generates a normal Django form, so your best bet for custom styling is to explore how to style Django forms first.
I would recommend Django Crispy Forms as I have used it to customise how fields are presented and it worked well.
Their docs have a specific mention about how to override how required fields are rendered.
https://django-crispy-forms.readthedocs.io/en/latest/crispy_tag_forms.html#change-required-fields
Otherwise you could just use some custom CSS to put the icon where you need it for fields with the required attribute.
https://developer.mozilla.org/en-US/docs/Web/CSS/:required

Accessing the Input Type from forms in Django

I am trying to access the Input Type to use in HTML but it appears to coming through as blank.
According to:
Django: How to access form field input_type in a template
I should be using:
{{field.field.widget.input_type}}
But it seems to be returning blank.
CODE:
{% for field in form %}
<div class="form-group">
<label class="control-label" for="id_{{ field.name }}">{{ field.label }}</label>
<input type="{{field.field.widget.input_type}}" class="form-control"
name="{{ field.name }}"
id="id_{{ field.name }}"
value="{{ field.value }}" >
</div>
{% endfor %}
Thanks very much in advance.
I think an easier way to do that is by adding the HTML class to the field properties. You can do this by.
field = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
In that whay, you would only need to do:
<label class="control-label" for="id_{{ field.name }}">{{ field.label }}</label>
{{ field }}
edit: models -> forms

Get field type in Django's login template

I'm trying to create custom template for Django's build-in login view. At the moment it looks like (registration/login.html):
<form method="post">
{% csrf_token %}
{% for field in form %}
{% include 'registration/form_field.html' %}
{% endfor %}
<input class="btn btn-primary btn-block" type="submit" value="{% trans "Log in" %}">
</form>
And registration/form_field.html file is:
<div class="form-group {% if field.errors %}has-error{% endif %}">
<input class="form-control" name="{{ field.name }}" placeholder="{{ field.label }}" {% if field.data %}value="{{ field.data }}"{% endif %} />
{% if field.errors %}
<span class='text-danger'>{{ field.errors|join:'<br>' }}</span>
{% endif %}
</div>
Everything works as expected, only problem is that password is shown in clear text.
To solve this type="password" should be set for password field (and type="text" for username field).
Is it possible to implement this using field variable (i.e. something like {{ field.type }})?
You can implement a PasswordInput widget in your form definition, that will render as a password field with type="password".
class ExampleForm(forms.Form):
password = forms.CharField(label='Password',
widget=forms.PasswordInput())
In the templates,
{{form.password}}
will render this field, which is the cleanest solution.
You may also access the type of the field (as you wanted), like this:
{{form.fields.password.widget.input_type}}
Note that if you'd like further customization beyond simply rendering the form, there's nothing wrong with just writing your own html for the fields.

Looping through Django Templates

I want to change the classes / attributes of the input fields of a ModelForm, but I'd like to do it from the template if possible.
Below is my solution for this, using the django django-widget-tweaks
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
{{form.title|add_class:"form-control"|attr:"placeholder:Title"|attr:"type:text"}}
</div>
<div class="form-group">
{{form.description|add_class:"form-control"|attr:"placeholder:Description"}}
</div>
<div class="form-group">
{{form.author|add_class:"form-control"|attr:"placeholder:Author"}}
</div>
<div class="form-group">
<input class="btn btn-primary" type="submit" value="Submit" />
</div>
</form>
My problem, is that this isn't very DRY, and I'm wondering if there's a better way to do this. I know django has looping over forms, but I'm not sure how I can integrate it while modifying the attributes.
Any help is appreciated.
You can take the placeholder and store it inside the field's help_text field. With that out of the way, you can easily loop through the fields like so:
{% for field in form %}
<div class="form-group">
{{ field|add_class:"form-control"|attr:field.help_text }}
</div>
{% endfor %}
Unfortunately it's hard/impossible to use a filter as for the second argument, so you will need to set help_text to 'placeholder:%s' where %s is your desired value.
If you're using a regular form, then set help_text in the constructor. But if you're using model form, I think it would be best to create a new template tag that can create the 'placeholder:%s' string for you from the field title:
#register.assignment_tag
def get_placeholder_arg(field):
return 'placeholder:%s' % field.label
Then your code would look like this:
{% for field in form %}
{% get_placeholder_arg field as arg %}
<div class="form-group">
{{ field|add_class:"form-control"|attr:arg }}
</div>
{% endfor %}
See the django documentation on custom template tags for details.

Categories