Reference list items by index Django template - python

I have a list called forms which I am passing to a Django (1.5.1) template:
<div class="content">
{% if forms %}
<form method="POST" enctype="multipart/form-data" class="survey">
<div class="image">
{{ forms.0.as_p }}
</div>
<div class="questions">
{% for form in forms %}
{{ form.as_p }}
</div>
{% endfor %}
<input type="submit" value="Submit Survey"/>
</form>
{% endif %}
<div class="content">
I want to do two separate things:
Put the first element of the forms list inside a div tag with class="image".
Put the rest of the elements inside a div tag with class="questions"
There are SO questions about how to reference list items by index inside a django template, but forms.0.as_p doesn't render anything for me. Also, how to get a sublist of items from forms (something like forms[1:])?
EDIT
While the question has been correctly answered below, I'll add another way of doing it using slice.
<form method="POST" enctype="multipart/form-data" class="survey">
<div class="image">
{{ forms.0.as_p }}
</div>
<div class="questions">
{% with myforms=forms|slice:"1:"%}
{% for form in myforms %}
{{ form.as_p }}
{% endfor %}
{% endwith %}
</div>

Use the forloop.first variable to determine the first form in the list:
{% for form in forms %}
<div class="{{ forloop.first|yesno:'image,question' }}">
{{ form.as_p }}
</div>
{% endfor %}
P.S. You don't need it for this case but to get the sublist in the template you can use the slice template filter.

Related

Django: Extent with snippets or better solution

I have the following template:
{% extends "account/base.html" %}
{% load i18n %}
{% load account %}
{% load crispy_forms_tags %}
{% block head_title %}{% trans "Password Reset" %}{% endblock %}
{% block content %}
<div class="container">
<div class="row justify-content-center">
<div class="col-8">
<h1>Reset your password</h1>
{% if user.is_authenticated %}
{% include "account/snippets/already_logged_in.html" %}
{% endif %}
<p>{% trans "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %}</p>
<form method="POST" action="{% url 'account_reset_password' %}" class="password_reset">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Reset My Password</button>
</form>
<p><em>{% blocktrans %}Please contact us if you have any trouble resetting your password.{% endblocktrans %}</em></p>
</div>
</div>
</div>
{% endblock %}
account/base.html contains this here:
{% extends "base.html" %}
base.html then contains tags etc. I am currently struggling with finding the best solution while considering DRY. In my template I have written:
<div class="container">
<div class="row justify-content-center">
<div class="col-8">
[more text]
</div>
</div>
</div>
I have several of these templates and in each of them I am currently writing the same ... I am now wondering is the right solution to include these opening / closing div-tags in two files and then add
{% include "div-open.html" %}
[more text]
{% include "div-closing.html" %}
Or is there any better solution to this? It doesn't feel right, that's why I am asking you now how you would solve this.
I depends if HTML repetition should be considered as DRY violation. I you have custom form fields which you want to include, than having {% include 'simple_custom_field.html' with field=form.some_fied %} where
simple_custom_field.html
<input
type="{{ field.field.widget.input_type }}"
class="form-control {{ field.field.widget.attrs.class }} {{ class }}"
id="{{ field.id_for_label }}"
name="{{ field.html_name }}"
placeholder="{{ field.label }}"
{% if field.value is not None %} value="{{ field.value }}"{% endif %}>
or like that...
is good idea, or you can render whole form like that also if you have long blocks or separate blocks of HTML in multiple files, then go for it. But its bad idea for including simple and fundamental parts of HTML. It should be transparent for the programmer.
If you want to do it another way, there are ways how to add custom template tags and "modify" the language you write templates in.
Here is docs how to do it: Writing custom template tags | Django docs

Flask square brackets and single quotas at showing all validation message at once

I have created a very simple login form with flask
email = StringField('E-Mail:', validators=[validators.DataRequired(message='E-mail needed.'), validators.email(u'Provide e-mail.')])
password = StringField('Password:', [validators.required(u'Password can't be empty.')])
And the macro which will create the form inside the template:
{% macro render_field(field) %}
<fieldset>
<div class="form-group">
{{ field(**kwargs) | safe }}
</div>
</fieldset>
{% endmacro %}
As you can see it is very simple form. In the flask tutorial it was showing validation erors for individual fields. But I just want to show them all at once on the top of the form.
Here is my template for that:
<div class="panel-body">
{% if loginForm.errors %}
<div class="alert alert-danger">
<ul>
{% for error in loginForm.errors %}
<li>{{ loginForm.errors[error] }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<form role="form" method="post" action="{{ url_for('login') }}">
{% from "_formhelper.html" import render_field %}
<fieldset>
{{ render_field(loginForm.email, class="form-control", placeholder="E-Mail") }}
{{ render_field(loginForm.password, class="form-control", placeholder="Password") }}
<button class="btn btn-lg btn-success btn-block">Login</button>
</fieldset>
</form>
</div>
As you can see, i placed my error section on the top of the form. But when
I post empty form, it shows the error messages like this:
['Password can't be empty'] instead of Password can't be empty
Why does it append square brackets and single quotas, start and end of the message? I don't know.
I know that this is an old question but if anyone else has this problem you can fix it by adding a for loop for the messages, something like this:
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="alert alert-warning my-5">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}

Render Flask wtforms RadioField lines/buttons in an ordered list

I would like to know if it's possible to have Flask WTForms RadioField render the list of radio buttons in an ordered list instead of an unordered list. My current jinja2 template is as follows:
{% extends "base.html.j2" %}
{% block content %}
<form action="/test" method="POST">
{% if test_form.errors %}
{{ test_form.errors }}
{% endif %}
{{ test_form.csrf_token }}
{% for qa in test_form.question_attempts %}
<div class="well">
<div>
{{ qa.label }}
</div>
<div>
{{ qa }}
</div>
</div>
{% endfor %}
{{ test_form.submitfield(class="btn btn-success") }}
</form>
{% endblock %}
Where the qa variable is the RadioField input.
EDIT:
To clarify, the test_form contains a list of RadioFields, which are the question_attempts. What I would like to do is have each qa render the radio buttons and associated radio button text in an ordered list rather than an unordered list.
When reviewing the WTForms documentation I had initially missed the part underneath the RadioFields description which describes how the list of radio buttons are rendered by default. I'll show it below:
{% for subfield in form.radio %}
<tr>
<td>{{ subfield }}</td>
<td>{{ subfield.label }}</td>
</tr>
{% endfor %}
This ends up rendering the radio buttons and associated text in an unordered list. Since I'm making an app where users can take a test, I wanted to render the answer choices in a list of "A. B. etc." This was fairly easy to do - I just needed to explicitly specify how the radio fields in my question_attempt form needed to be rendered. I'll show my updated code below:
{% extends "base.html.j2" %}
{% block content %}
<form action="/test" method="POST">
{% if test_form.errors %}
{{ test_form.errors }}
{% endif %}
{{ test_form.csrf_token }}
{% for qa in test_form.question_attempts %}
<div class="well">
<div>
{{ qa.label }}
</div>
<div>
<ol type="A">
{% for subfield in qa.answer_selection %}
<li>
{{ subfield }}
{{ subfield.label }}
</li>
{% endfor %}
</ol>
{{ qa.question_id }}
</div>
</div>
{% endfor %}
{{ test_form.submitfield(class="btn btn-success") }}
</form>
{% endblock %}
Now the form renders the radio button fields in and ordered list!
While explicitly writing the template will give you more control for how the fields are rendered, you then need to make sure that each component of the form is rendered in the template. Otherwise data from those fields will not be included in the posted data. This will be obvious for fields that require user input (as you won't see them), but can cause problems if you're using hidden fields for housekeeping data.

Using stylesheets with django-widget-tweaks?

I'm struggling to understand how to use Django-Widget-Tweaks with a stylesheet. For example, here's my basic form with bunch of CSS classes pulled from my stylesheet - obviously not yet wired up with Django.
<form name="form">
<div class="md-form-group float-label">
<input type="email" class="md-input">
<label>Email</label>
</div>
</form>
How should this be used with Django-Widget-Tweaks? I'm presuming it's something like this but I'm struggling to understand where the div classes go...
<div>
{% load widget_tweaks %}
{{ form.myform|add_class:"md-form-group float-label md-input" }}
</div>
Thanks!
This is how I do it by using render_field tag. Hope this helps.
{% load widget_tweaks %}
<form name="form">
{% for field in form %}
<div class="md-form-group float-label">
{% render_field field class="md-input" %}
<label>{{ field.label_tag }}</label>
</div>
{% endfor %}
</form>

Django forms adding <div> after form field

Below is my form code :
class FMessage(forms.Form):
From = forms.CharField()
To = forms.CharField()
Subject = forms.CharField()
Message = forms.CharField()
and this is my html code:
<form method='POST' action='.'>
{% csrf_token %}
{{ form.as_p }}
<input type='submit' value='submit'>
</form>
The code works fine by displaying forms and has not any issue in functionality, but now I need to wrap my form fields in html by a div like this:
<div id='mydiv'>
<input ... />
<div>
How can I fix it?
Seems like you do not really want to use the inbuilt <p> or <table> wrapped forms and rather want to display the fields wrapped within a <div>'s. You can simply iterate over fields in the form as follows.
{% if form %}
<!-- Form Errors -->
{% if form.errors %}
<ul class="errors">
{% for error in form.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<!-- Display Form -->
<form>
{% csrf_token %}
{% for field in form %}
<div class="mydiv">
<label class="mylabel">{{ field.label }}</label>
{{ field }}
</div>
{% endfor %}
</form>
{% endif %}
Dont render the form by using form.as_p. You need to show each field of the form, for example, by using form.to. By using this way, you can wrap the field 'to' into a div
<div>{{ form.To}} </div>
For more detail, view this link

Categories