Hello everyone!
We all know that
Django is a very powerful and dynamically developing framework for creating web applications. However, despite the advent of the Web 2.0 era, there are still no built-in mechanisms for working with
AJAX , in particular, sending and checking forms. Perhaps django simply does not want to impose some js framework on the user and wants to remain flexible in this matter, but one way or another, development often requires forms that work via ajax, without page reloads.
The creation of such forms and work with them will be discussed in this article.
At once I will make a reservation that the idea is not new, and there are several libraries that implement the required functionality, for example, one of them is
http://www.dajaxproject.com/ .
For those who prefer to manage the client’s interaction with the server themselves or those who don’t want to draw an additional library into the project and deal with its bugs, I’ll tell you how to
invent a bike to implement the mechanism yourself and describe various ways to solve the problem.
The form
For example, take a simple user registration form on the site:
class RegisterForm(forms.Form): email = forms.EmailField() password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput) password2 = forms.CharField(label=_("Password confirmation"), widget=forms.PasswordInput)
In real life, you will most likely inherit this form from the data model, but for our example this is not essential.
')
Form output
To display this form on the page we have two options:
- Make a container with display: none within all pages from which you can call a form (or within the parent template), then use JS to create a dialog from this container.
- Load the form via ajax from a separate URL, and then also create a dialog.
The advantage of the first option is in its speed (no additional requests to the server should be made), but in the second option you can use the same
view to process
GET and
POST requests to the form (we will need POST in both cases), plus we make a separate a template file for form output, which makes the code structure more orderly, although this is of course a matter of taste.
Personally, I embed something in a page template only if it is a simple
yes / no dialog, and for forms I always use separate
views .
Therefore, we’ll stop here on a separate view for the form, then the code will look like this:
- view :
def register(request): form = RegisterForm() return direct_to_template(request, "register.html", extra_context={'form': form })
- template :
{% load i18n %} <form id="register_form" method="post" action="{% url register %}"> {% csrf_token %} <ul> {{ form.as_ul }} <li><span id="register">{% trans "Register" %}</span></li> </ul> </form>
Form processing
We proceed to the processing of the form. Here it is necessary to take into account that the ajax handler must somehow understand whether the form has been successfully verified or contains errors. The logical solution here, in my opinion, is to use
JSON . The server response will contain 2 parameters, the first of which is boolean, will report on the success or failure of the validation form. With the second parameter, again, there are various options:
- In case of successful verification of the form, this parameter may be empty, since the login form most likely redirects the user to the required url after logging in and it does not matter what is there, or it may be a string that needs to be displayed in the confirmation dialog.
- In the case when there are errors in the form again, there are 2 possible ways of displaying:
- The first way is to re-render the form with errors through the template and place the entire html-response in a json-variable, which then replaces the contents of the entire form.
- The second way is to create an array of errors for all fields of the form and place it in a json variable, then output errors for each field in the loop.
I like the second option ideologically more, because it displays only what is needed, without replacing the entire form. Here I will show how to implement both methods. The client-side form processing code uses the popular
jQuery JS framework and its plugin called
jQuery Form Plugin .
- The first way:
Final version view :
def register(request): if request.method == 'POST': form = RegisterForm(request.POST) if form.is_valid():
Client-side processing, javascript:
$(document).ready(function() { $('#register').live('click', function() { $('#register_form').ajaxSubmit({ success: function(data, statusText, xhr, $form) {
- The second way:
Final version view :
def register(request): if request.method == 'POST': form = RegisterForm(request.POST) if form.is_valid():
Client-side processing, javascript:
function display_form_errors(errors, $form) { for (var k in errors) { $form.find('input[name=' + k + ']').after('<div class="error">' + errors[k] + '</div>'); } } $(document).ready(function() { $('#register').live('click', function() { $('#register_form').ajaxSubmit({ success: function(data, statusText, xhr, $form) {
It is also worth noting that when using the second method and the form template described earlier, errors will be displayed using the list item
<ul> ; for another display, you need to make a different template or override the error class for the form.
That's all. I attach screenshots of the resulting form in various states:

I will be glad to hear comments and learn other ways to work with ajax-forms.