I just created a generic view for Django which allows a developer to easily add AJAX-style form validation to a newforms based form.
The system needs one server-side view, and some client-side JavaScript. You can find the view code in my Django snippets Git repository. The view only works with POST requests. It takes a standard HttpRequest and some options:
- form_class: this parameter defines the newforms class to validate against. It can be specified in the extra args parameter of the view’s urlconf. If you don’t specify it, the ‘form_class’ POST field will be used. If this doesn’t exist either, an exception is raised. The parameter can be a newforms form instance, a string, or a class (which should be a subclass of BaseForm).
- format: the serialization format to use. Currently only ‘json’ is supported.
- args: extra argument list to provide to the form constructor (shouldn’t be provided in most cases)
- kwargs: extra argument dics to provide to the form constructor (shouldn’t be provided in most cases)
Next to the server-side view you’ll need some pretty basic JavaScript code on client side. I use JQuery and the JQuery Form plugin. Here’s some sample code, assuming the form ID is ‘my_form’, and form fields are represented like this:
<p id="{{ form.field.name }}_container"><label for="{{ form.field.auto_id }}">{{ form.field.label|capfirst }}:</label>{{ form.field }} {% if form.field.errors %}<span id="{{ form.field.name }}_error" class="error">{{ form.field.errors.0 }}</span>{% endif %} </p>
Here’s the corresponding JavaScript code:
function do_something() { } function process_validation(data) { if(data['form_valid'] == true) { do_something(); return; } for(var field in data["errors"]) { errors = data["errors"][field] if(errors.length > 0) { error = errors[0]; if($("#" + field + "_error").length == 0) { s = $("<br /><span style=\"display: none;\" id=\"" + field + "_error\" class=\"error\">" + error + "</span>"); $("#" + field + "_container").append(s); } $("#" + field + "_error").html(error).fadeIn("slow"); } } } function validate_form(data) { data.push({name: 'form_class', value: 'project.application.forms.ApplicationForm'}); $.post("{% url validate_form %}", data, process_validation, "json"); } $(document).ready(function() { $("#my_form").submit(function() { data = $("#my_form").formToArray(); $(".error").fadeOut("slow"); validate_form(data); return false; }); });
Obviously this should be changed to suit your needs.
I hope this code can be useful for someone…
I’m wondering what is happening when you are clicking many times.
$(“.error”).fadeOut(“slow”);
This is a bit “light”, you should remove them from the DOM after fading them out. And please remove the br you are using or put it the error class name too.
By the way, it’s a nice and useful idea.
Cheers,
That’s up to the client side developer I guess, I must admit I’m not that good at JavaScript/DOM coding.
Clicking many times is not an issue as the existing container is re-used if it already exists.
The BR is there to make things look good, I don’t now whether there’s better markup…
Thanks for the constructive comment
You’re right about the container, sorry.
You shouldn’t load the server for testing a form anyway, reactivity is important so use Ajax carefully
You’re right there. A really nice project would be to add client-side form validation code generation to Django’s newforms, so I could do something like:
I started the above mentioned project, see http://eikke.com/tag/django-validation/ Enjoy!
,
Smotri i y4is,
nice validation, first time i’ve set somthing like this up.. works well. Thank you.
Cool scripting… bit complex for me, but i’ll figure it out!