Django form template - django

If there were field.errors in django, how to to add css class to {{ field }}, example at bottom
{% for field in form %}
{{ field }}
{% if field.errors %}{{ field.errors }}{% endif %}
{% endfor %}
Aiming for {{ field }} input type that would have "class=error" when ever there was an error
<input class="error">

You can add the class to a wrapper around the field. Django also does this by itself when defining classes in forms.py or views.py
{% for field in form %}
<p {% if field.errors %}class="error"{% endif %}
{{ field }}
</p>
{% if field.errors %}{{ field.errors }}{% endif %}
{% endfor %}
Unfortunately this seems to be the only way.
Even when Django adds the classes itselt, it prefers to add them to a wrapper of some sort.
http://docs.djangoproject.com/en/dev/ref/forms/api/#more-granular-output
Scroll down to read about the new thing in 1.2 about adding css classes.
Using this, you can just use form.as_p (or whatever suits you) as the elements will have all the classes as you define them.
Hope this was a little bit of help.

You can use widget_tweaks api to do that.
Instead of rendering a form with
{{ form.field }}
You should use:
{% load widget_tweaks %}
{% render_field form.field class="error" %}

Related

How to keep 2 fields using django forms

As django forms run a loop for the fields
{% for field in form %}
<div class="col-6">
{{ field.errors }}
{{ field.label_tag }}
{{ field }}
</div>
{% endfor %}
I actually want to have 2 fields, I found a cheap solution to this issue using Bootstrap4
I created the columns by using col-6 by which I get 2 fields in the row. But what if I want to make custom designs of forms in django ?
Personally i am using this method to show only fields i want and then have if statements for the way each field should be shown
{% for i in form %}
{% if i.name in 'title,address,city' (Fields you want to show) %}
{% for error in i.errors %}
<div>
<li><strong>{{ error|escape }}</strong></li>
</div>
{% endfor %}
<p>
<label>{{i.label}}:</label>
<input type="text" name="{{i.name}}" required id="id_{{i.name}}">
</p>
{% endif %}
{% endfor %}
And like that you can style it however you want and show only those you want to show

What is form.visible_fields in Django and how do I index into it?

Sometimes I have the need to render a particular Django form field in a particular way. I would like to be able to access this field and only this field in order to customize its rendering in my template.
I know, for example, that I can do something like this:
<!--Access the form field at index 2-->
{% for field in form.visible_fields %}
{% if forloop.counter == 2 %}
<!--Render my form field the way that I want to-->
{% endif %}
{% endfor %}
Intuitively, I would expect to be able to do something like {{ form.visible_fields[2] }} or perhaps {{ form.visible_fields['field_name'] }}.
Unfortunately, my various attempts at the above have all failed and so I'm left wondering if this is possible. Any advice?
According to Django documentation you should be able to something like this:
{# Include the hidden fields #}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{# Include the visible fields #}
{% for field in form.visible_fields %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}

Django: For Loop to Iterate Form Fields

I don't want to use django's built in form generation, seeking to specify each field in my template in order to customize the html output.
How do I iterate over a series of form fields?
If my form looks like this:
class MyForm(forms.Form):
main_image = forms.ImageField()
second_image = forms.ImageField()
third_image = forms.ImageField()
fourth_image = forms.ImageField()
...
Is there way to write a {% for %} loop so that I can iterate through:
{{ form.main_image }}
{{ form.second_image }}
{{ form.third_image }}
{{ form.fourth_image }}
I tried the following which seemed logical, but did not work:
{% for field in form %}
{{ form.field }}
{% endfor %}
Well this would clearly not work:
{% for field in form %}
{{ form.field }}
{% endfor %}
but this will:
{% for field in form %}
{{ field }}
{% endfor %}
The best way is to use two loops, one for hidden fields and one for visible fields :
visibles:
{% for field in form.visible_fields %}
{{ field.label }}
{{ field }}
{% endfor %}
hiddens:
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
in this way you will have better control over UI elements.
This one should work :
{% for field in form %}
{{ field }}
{% endfor %}
Once you loop through field in form , you can't access form.field
For any frontend developers looking to customize a Django form you can use a package called django-widget-tweaks to render fields individually. Example code below:
{# Your template with the form #}
{% extends "base.html" %}
{% load widget_tweaks %}
<form action="" method="POST">
{% csrf_token %}
{% for field in form %}
<label for="{{ field.id_for_label }}">
{{ field.label }}{% if field.field.required %}*{% endif %}
</label>
{% render_field field %}
{% endfor %}
<button type="button">
Submit Form
</button>
</form>
Note: You'll want to make this look nicer of course, and you may want to loop through your form errors if there are any.
They have some very useful examples on their PyPi page as well.

ListField is showing <ul> instead of <input> in edit/create post

I am using Flask, mongoengine for a project and I am trying to get basic stuff working from http://docs.mongodb.org/manual/tutorial/write-a-tumblelog-application-with-flask-mongoengine/
After implementing everything from above link I added a new field for "tags" in Post and when I try to create a post, my tags doesn't show a input box.
Any help is appreciated.
My code and screenshot below
class Post(db.DynamicDocument):
created_at = db.DateTimeField(default=datetime.datetime.now, required=True)
title = db.StringField(max_length=255, required=True)
slug = db.StringField(max_length=255, required=True)
comments = db.ListField(db.EmbeddedDocumentField('Comment'))
tags = db.ListField(db.StringField(max_length=30)) # New field I added
template form
{% macro render(form) -%}
<fieldset>
{% for field in form %}
{% if field.type in ['CSRFTokenField', 'HiddenField'] %}
{{ field() }}
{% else %}
<div class="clearfix {% if field.errors %}error{% endif %}">
{{ field.label }}
<div class="input">
{% if field.name == "body" %}
{{ field(rows=10, cols=40) }}
{% else %}
{{ field() }}
{% endif %}
{% if field.errors or field.help_text %}
<span class="help-inline">
{% if field.errors %}
{{ field.errors|join(' ') }}
{% else %}
{{ field.help_text }}
{% endif %}
</span>
{% endif %}
</div>
</div>
{% endif %}
{% endfor %}
</fieldset>
{% endmacro %}
rendering form code
{% extends "admin/base.html" %}
{% import "_forms.html" as forms %}
{% block content %}
<h2>
{% if create %}
Add new Post
{% else %}
Edit Post
{% endif %}
</h2>
<form action="?{{ request.query_string }}" method="post">
{{ forms.render(form) }}
<div class="actions">
<input type="submit" class="btn primary" value="save">
Cancel
</div>
</form>
{% endblock %}
From what I can gather, your problem is you're telling WTF to render the tags field, but WTForms doesn't know how to handle that information.
From looking at the Flask-MongoEngine documentation, it seems the ListField is just a FieldList as WTForms refers to it.
Currently you're not actually defining the form independently in WTForms, you're just using the magic included in Flask-MongoEngine, so my first attempt would be to add some more logic to your macro, add a {% elif field.type == 'ListField' %} and try and discover what's contained in there to iterate through to produce your form. From having a quick look at the source-code, something like the following might work.
{% elif field.type == 'ListField %}
{# render_the_group_label #}
{% for subfield in field.entries %}
{% if subfield.type == 'StringField' %}
{# render_the_subfield #}
{% endif %}
{% endfor %}
...
That code will need to be worked on, but hopefully it'll point you in the right direction. Otherwise, I'd actually define the form seperately in WTForms to give you a bit more control on the code-side. Luckily they provide a csv tag example which should help you if you need to go that route. I wrote a guide that takes a different route using #property decorators to achieve a similar effect, which again, might at least point you towards the finish line.

Customizing a Django admin template

I would like to modify an admin template in Django.
% cat /Library/Python/2.5/site-packages/django/contrib/admin/templates/admin/includes/fieldset.html
<fieldset class="module aligned {{ fieldset.classes }}">
{% if fieldset.name %}<h2>{{ fieldset.name }}</h2>{% endif %}
{% if fieldset.description %}<div class="description">{{ fieldset.description|safe }}</div>{% endif %}
{% for line in fieldset %}
<div class="form-row{% if line.errors %} errors{% endif %} {% for field in line %}{{ field.field.name }} {% endfor %} ">
{{ line.errors }}
{% for field in line %}
<div{% if not line.fields|length_is:"1" %} class="field-box"{% endif %}>
{% if field.is_checkbox %}
{{ field.field }}{{ field.label_tag }}
{% else %}
{{ field.label_tag }}{{ field.field }}
{% endif %}
{% if field.field.field.help_text %}<p class="help">{{ field.field.field.help_text|safe }}</p>{% endif %}
</div>
{% endfor %}
</div>
{% endfor %}
</fieldset>
What kind of object is field, and more specifically how would I get the name of a field?
field is an instance of AdminField and field.field is an instance of BoundField, so you can reference the fields name with:
{{ field.field.name }}
Once as you start to dive deep into admin customisation, its the only place the documentation is really lacking. that being said, the code is well written and easy to understand if you take the time to research it, IMHO.
There is not many files so take an evening and read through them. In your case, I would start with:
contrib/admin/sites.py
contrib/admin/options.py
contrib/admin/helpers.py
Have you done your research?
After that, I would start poring over the python code that invokes your template. I would imagine that field is from the forms system
Field
A class that is responsible for doing validation, e.g. an EmailField
that makes sure its data is a valid
e-mail address.