27👍
As of Django 1.11, you can just use widget.input_type
. Example:
{% for field in form.visible_fields %}
<input type="{{ field.field.widget.input_type }}"
id="{{ field.id_for_label }}"
name="{{ field.html_name }}"
placeholder="{{ field.label }}"
maxlength="{{ field.field.max_length }}" />
{% endfor %}
45👍
Making a template tag might work? Something like field.field.widget|widget_type
Edit from Oli: Good point! I just wrote a filter:
from django import template
register = template.Library()
@register.filter('klass')
def klass(ob):
return ob.__class__.__name__
And now {{ object|klass }}
renders correctly. Now I’ve just got to figure out how to use that inside a template’s if
statement.
Edit from Oli #2: I needed to use the result of that in an if statetement in-template, so I just shifted all that logic into the templatetag. Magic. Thanks for poking me in the right direction.
- [Django]-Handle `post_save` signal in celery
- [Django]-Django Celery Logging Best Practice
- [Django]-How to get a list of all users with a specific permission group in Django
37👍
Following up on the accepted answer – the enhanced if tag
in Django 1.2 allows you to use filters in if tag
comparisons. So you could now do your custom html/logic in the template like so:
<ul>
{% for field in form.fields %}
<li>
{% if field.field.widget|klass == "Textarea" %}
<!-- do something special for Textarea -->
<h2>Text Areas are Special </h2>
{% else %}
{{ field.errors }}
{{ field.label_tag }}
{{ field }}
{% endif %}
</li>
{% endfor %}
</ul>
- [Django]-What's the best way to start learning django?
- [Django]-How to query as GROUP BY in Django?
- [Django]-What is the difference render() and redirect() in Django?
21👍
Following the answer from Oli and rinti: I used this one and I think it is a bit simpler:
template code: {{ field|fieldtype }}
filter code:
from django import template
register = template.Library()
@register.filter('fieldtype')
def fieldtype(field):
return field.field.widget.__class__.__name__
- [Django]-Difference between 'related_name' and 'related_query_name' attributes in Django?
- [Django]-Best practices for adding .gitignore file for Python projects?
- [Django]-How does one make logging color in Django/Google App Engine?
1👍
Perhaps worth pointing out to contemporary readers that django-widget-tweaks
provides field_type
and widget_type
template filters for this purpose, returning the respective class names in lowercase. In the example below I also show the output of the input_type
property on the field widget (since Django 1.11), which may also be useful.
forms.py
:
class ContactForm(forms.Form):
name = forms.CharField(
max_length=150,
required=True,
label='Your name'
)
template.html
:
{% load widget_tweaks %}
{% for field in form.visible_fields %}
{{ field.label }}
{{ field.field.widget.input_type }}
{{ field|field_type }}
{{ field|widget_type }})
{% endfor %}
Result:
Your name
text
charfield
textinput
Between these various options you should be able to find the right property to target for just about any use-case. If you need to capture the output of one of these filters for use in if
statements, you can use the with
template tag.
- [Django]-Django Model Fields Indexing
- [Django]-Django development IDE
- [Django]-Iterate over model instance field names and values in template
0👍
You can make every view that manages forms inherit from a custom generic view where you load into the context the metadata that you need in the templates. The generic form view should include something like this:
class CustomUpdateView(UpdateView):
...
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
...
for f, value in context["form"].fields.items():
context["form"].fields[f].type = self.model._meta.get_field(f).get_internal_type()
...
return context
In the template you can access these custom properties through field.field:
{% if field.field.type == 'BooleanField' %}
<div class="custom-control custom-checkbox">
...
</div>
{% endif %}
By using the debugger of PyCharm or Visual Studio Code you can see all the available metadata, if you need something else besides the field type.
- [Django]-How to change status of JsonResponse in Django
- [Django]-Manage.py runserver
- [Django]-Django ModelForm override widget
0👍
For anyone here whose purpose is to customise widget style according to its type, based on @oli answer great idea, I decided to set the mapping directly in the template filter, and return the corresponding classes directly. This avoids messing with {% if %}
statements in the template.
from django import template
register = template.Library()
BASIC_INPUT = "border border-indigo-300 px-2.5 py-1.5 rounded-md focus:outline-none"
mapping = {
"Select": BASIC_INPUT,
"TextInput": BASIC_INPUT,
"EmailInput": BASIC_INPUT,
"RegionalPhoneNumberWidget": BASIC_INPUT,
"ModelSelect2": "", # let the default markup
}
@register.filter("get_field_classes")
def get_field_classes(field):
widget_class_name = field.field.widget.__class__.__name__
try:
return mapping[widget_class_name]
except KeyError:
raise ValueError(f"Classes related to {widget_class_name} are not defined yet")
Then in your default form template (e.g: django/forms/default.html
), when browsing fields, with the help of django-widget-tweaks package:
{% load widget_tweaks %}
{% load get_field_classes %}
{% for field in form.visible_fields %}
{# .... #}
<div>
{% with field_classes=field|get_field_classes %}
{{ field|add_class:field_classes }}
{% endwith %}
</div>
{% endfor %}
- [Django]-Connect to a DB using psycopg2 without password
- [Django]-Django: manage.py does not print stack trace for errors
- [Django]-No handlers could be found for logger