django: adding * to every required field
It is almost a standard to mark required fields on a web form with *. While working on django newforms (now forms) I realized quite late that the as_* methods of forms do not mark required fields with *. A straight forward way would have been to write an inclusion tag and just render the form, as mentioned; IF I was starting the app. But when you evolve your app from a single page, almost all of your forms are going to be rendered using as_* methods. And if you are as lazy as me, you’ll definitely get cramps just by thinking about all the possible changes.
So i started thinking, “How do I mark all the required fields with * while keeping the as_* methods?”. Determined not to change the templates; I sniffed around the django code for a couple of hours, tried many variation and finally found a lazy (not too pretty
) way around this issue. The code for this solution is following,
from django.newforms.forms import BoundField __init__temp = BoundField.__init__ def __my_init__(self, form, field, name): __init__temp(self, form, field, name) if self.field.required: self.label += '*' BoundField.__init__ = __my_init__
For those who are in a hurry, copy and paste the above code at the top of your forms.py file.
Now for the explanation. When a BoundField is created, it gets its label from the field. If we can somehow hook into the __init__ method of BoundField and change the label, we an get our desired result. In this code snippet,
- save the BoundField.__init__ method in __init__temp__ and replace it with my own implementation (__my__init__).
- In __my__init__, call the old __init__ method (saved in __init__temp__)
- append ‘*’ to the BoundField.label if field is required.
This way, you dont have to change anything in your templates and yet mark all required fields as ‘*’. I am not sure if this is an smart hack or an ugly hack? Writing an inclusion template seems the right approach in long-term. But if you are looking for a quick solution, this serves the purpose.
Related posts:



I’m confused. How does putting this in my forms.py alter the behavior of BoundField?
Andrew,
A BoundField object is created for every field in your form object. This code replaces the normal __init__ method of BoundField with __my_init__. So when an object of BoundField is created, __my_init__ will be called instead of __init__. In this new method, I call the original __init__ first for proper initialization then change the BoundField label if field is required.
With latest SVN the code above will issue a DeprecationWarning (you should import django.forms.forms); anyway you may want to look at the AdminField class in admin sources in django (django/contrib/admin/options.py), since the admin app marks required fields with bold text and does this in a cleaner way (basically manipulating the .label attribute of BoundField). And you can consider marking the * with a proper class so it can be styled with CSS.
Actually, its not mentioned how you check for a required field on those pages in a forms template file? Its actually a bit of a pain in the back side and this hack seems the only quick solution as far as I can tell…?!
It is also possible to access this property from within a template, using field.field.required.
Like so:
{% for field in form %}
{{ field.label_tag }} {% if field.field.required %}*{% endif %}
{{ field }}
{% endfor %}
I left the error displaying out not to make the example to complex.
More info can be found at http://docs.djangoproject.com/en/dev/topics/forms/ .
@lgespee
Please corrent the typo I made:
… the example to complex. …
… the example too complex. …
Thanks
Good post,This was exactly what I needed to read today! I am sure this has relevance to many of us out there.
Nice stuff, thank you
Hi, very good web site. Thanks.
THis works well, but Igespee’s form field customisation is probably better practice.
Worth raising as a ticket to adjust the default behaviour of the as_* options in Django though, as it’s always valutable to have required or not in the class.
I want to thank you for taking time to post this, it was really helpful.
Great post! These are necessary things to stay in mind, it’s usually easy to forget concerning the easy things once you get consumed by a project.
I see, Thanks.