How to modify css class using jinja2 macro - python

Hi guys i'm learning flask and have a problem. I'm trying to modify a input form control class based on validation.
In the jinja2 template i have the following (i'm using render_field) have imported the macro:
{% from 'includes/_formhelpers.html' import render_field %}
<div class="form-group">
<div class="input-group input-group-alternative mb-3">
<div class="input-group-prepend">
<span class="input-group-text"><i class="ni ni-hat-3"></i></span>
</div>
{{ render_field(form.username, placeholder="Username",class="form-control") }}
</div>
</div>
And then in the macro file i have the following content:
{% macro render_field(field) %}
{{ field(**kwargs)|safe }}
{% if field.errors %}
{% for error in field.errors %}
<input class="form-control is-invalid">
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% endif %}
{% endmacro %}
The problem is that the macro in rendering another input box
Generated HTML:
<div class="form-group">
<div class="input-group input-group-alternative mb-3">
<div class="input-group-prepend">
<span class="input-group-text"><i class="ni ni-hat-3"></i></span>
</div>
<input class="form-control" id="username" name="username" placeholder="Username" required="" type="text" value="pandazulweb">
<input class="form-control is-invalid">
<div class="invalid-feedback">
Username already in use.
</div>
</div>
I think it's something related to kwargs and how i'm passing the class to the template but i'm a noob with jinja2

Unless I’m missing something, it looks like the second field is due to the ‘<input class=“form-control is-invalid”>’ which you’re including in the error condition of your macro.
EDIT: In order to pass the class to a form field, you need to use ‘class_=“is-invalid”‘, not ‘class=‘. So just use that and remove the second input from your error case.
EDIT 2: I think I see what the problem is. You need to put the first call to field() inside the macro’s error block, in the else block. So only if there is no error will it create the field with kwargs, etc.

Related

Error during template rendering using extra_context django

Hello I'm using extra_context in views and in the HTML I'm passing it, but it seems that I am doing it wrong because I get this error:
ProgrammingError at /informacion-tiendas/add
column InformacionTiendas_informaciontiendas.nombre does not exist
LINE 1: ...ECT "InformacionTiendas_informaciontiendas"."id", "Informaci...
And when commenting the extra_context line in views, the HTML page is already seen without errors, obviously the context does not pass and the inputs do not appear, but at least there are no errors
Does anyone know why?
views.py
class InformacionTiendasAdd(CreateView):
model=InformacionTiendas
form_class=InformacionTiendasForm
template_name='InformacionTiendas/informacion-tiendas-agregar.html'
success_url=reverse_lazy('InformacionTiendas:list_tiendas')
extra_context={'tiendas': InformacionTiendas.objects.all()}
models.py
class InformacionTiendas(models.Model):
nombre=models.CharField(max_length=255)
registro_desde=models.DateTimeField(default=datetime.now )
tax_id=models.IntegerField()
def __str__(self):
return f'{self.nombre} {self.registro_desde} {self.tax_id}'
informacion-agregar-tiendas.html
<form class="needs-validation" novalidate>
{% for tienda in tiendas %}
<div class="row mb-3">
<div class="col-md-12">
<div>
<label class="form-label" for="validationCustom01">Name</label>
{{ tienda.nombre }}
<div class="invalid-feedback">
Please provide the workshop name.
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label" for="validationCustom06">Registration</label>
{{ tienda.registro_desde }}
Please provide workshop`s registration number.
</div>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label" for="validationCustom07">TAX ID</label>
{{ tienda.tax_id }}
<div class="invalid-feedback">
Please provide workshop`s registration number.
</div>
</div>
</div>
</div>
{% endfor %}
</form>
Based on the new information from your edit, it looks like you haven’t migrated the database.
Try running this in your shell:
python manage.py makemigrations
python manage.py migrate

Get checkbox option names when redndering manually

I'm trying to get the name of each option associated with a particular checkbox element. For example when I allow django to render the checkbox it produces
<label for="id_amenities_0"><input name="amenities" value="1" id="id_amenities_0" type="checkbox">
Care Parking</label>
Now I'm trying to render the forms manually and I want to find a way of displaying 'Care Parking'. This is what I have done but it doesn't display anything
{% for box in form.amenities %}
<div class="col-12 col-md-4">
<label class="custom-checkbox" for="id_amenities_{{ forloop.counter0 }}"> {{ box.html_name }}
<input type="checkbox" id="id_amenities_{{ forloop.counter0 }}" name="amenities">
<span class="checkmark"></span>
</label>
</div>
{% endfor %}
You're looking for choice_label:
{% for box in form.amenities %}
<label>{{ box.choice_label }}</label>
{% endfor %}

Adding error class to outer div django widget-tweaks

I am currently working on forms with django-widget-tweaks, I want to add error class to div not in input, here is my code
<div class="form-group">
<label class="control-label" for="id_title">Title</label>
{% render_field form.title|add_class:"form-control"%}
</div>
if getting error it should be
<div class="form-group has-error">
<label class="control-label" for="id_title">Title</label>
<input type="text" name="title" value="akjdla" id="id_title" class="form-
control" required="" placeholder="Title" title="" maxlength="120">
<div class="help-block">This field is required.</div>
</div>
In documentation I found only adding the class in input, how can I add error class to outer div and show error down to it?
<div class="form-group" {% if form.title.errors %} has-error {% endif %}>
<label class="control-label" for="id_title">Title</label>
{{ form.title|add_class:"form-control" }}
<div class="help-block">{{ form.title.errors }}</div>
</div>

How do I reference an object property in a method call in Jinja2?

I am trying to render a form in a flask app using jinja2 and flask-wtf, but am having trouble figuring out how to handle adding a generated argument for onclick that contains a property as part of it's argument.
You can see in the form label section I have onclick set to call a javascript function and pass the name property of the current loop object and this works as intended. However when I am in the form field section, I need to pass onclick to the loop object as a key word argument, and need to make the argument of my argument the object name property. This doesn't work.
Here is a shortened example:
<form class="form">
{% for entry_field in form %}
{{ entry_field.label() }}
{{ entry_field(onclick="jsFunction({{entry_field.name}})}}
{% endfor %}
</form>
Here is a full example:
<form id="reg_form" class="form text-left" method="post" role="form">
{{ form.csrf_token }}
{% for entry_field in form %}
{% if entry_field != form.csrf_token %}
<div class="form-group row">
<!--form label-->
<a href="#" onclick="showNotes('{{entry_field.name}}')">
{{ entry_field.label(class="col-sm-3 col-form-label") }}
</a>
<!--form field-->
<div class="col-sm-9">
{{ entry_field(class_="form-control", onclick="showNotes('{{entry_field.name}}')") }}
{% for error in entry_field.errors %}<span style="color: red;">{{ error }}</span>{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}
<!--form submit-->
<div class="form-group row">
<div class="col-sm-9 col-sm-offset-3">
<input type="submit" class="btn btn-lg btn-success" value="Submit">
</div>
</div>
</form>
Greatly appreciate any help!
You can use string formatting to build a string you want:
{{ "jsFunction(%s)" | format(entry_field.name) }}
And that string you can use as the parameter for entry_field():
{{ entry_field(onclick=("jsFunction(%s)" | format(entry_field.name)) }}

Django form input field styling

I have redefined form for contact us page, It's standard django-form stuff, but I'm struggling to understand how can I write description inside <inpout> field.
To be precise I want to write Name inside <input> field, so how can I do this. I define <input> field like {{ form.name }}, so how can I define it more like <input type="name" class="form-control" id="id_name" placeholder="Your Name">.
<div class="col-xs-12 col-sm-12 col-md-4 col-md-offset-2 col-lg-4">
{% if form.errors %}
<p style="color: red">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<form class="form-horizontal" action="." method="POST">
{% csrf_token %}
<div class="field form-group">
{{ form.name.errors }}
<label for="id_name" class="control-label"></label>
<div class="col-sm-10">
{{form.name}}
</div>
</div>
<div class="field form-group">
{{ form.email.errors }}
<label for="id_email" class="control-label"></label>
<div class="col-sm-10">
{{ form.email }}
</div>
</div>
<div class="field form-group">
{{ form.phone_number.errors }}
<label for="id_phone_number" class="control-label"></label>
<div class="col-sm-10">
{{ form.phone_number }}
</div>
</div>
<div class="field form-group">
{{ form.message.errors }}
<label for="id_message" class="control-label"></label>
<div class="col-sm-10">
{{ form.message }}
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<input type="submit" class="btn btn-primary btn-block" value="Submit"></button>
</div>
</div>
</form>
</div><!--/end form colon -->
If you want to modify the placeholder text, or other values of the field Django creates, it can be done in the form code using the widget's attrs:
class MyForm(forms.Form):
name = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'my-class',
'placeholder': 'Name goes here',
}))
If your intention is to keep all of the code in the template you will have to manually create each input field instead of using the ones Django renders. You can still access the values of the generated field in the template to help you do that though.
<input name="{{ form.name.name }}" type="text" placeholder="Name field">

Categories

Resources