Back
Mar 6, 2010

Ajax form validation

There was a task to submit form with ajax, with server side validation of course. Obvious solution is to do validation and return json with erros.

I didn't like idea of writing separate view for validation and then inserting errors in form html on client side. Especially since I already had a generic template for django form with errors display.

Task

User will see process like this:

  • User clicks 'edit' near article block
  • article is replaced with form
  • in case there are validation errors - they are shown above the form fields
  • in case there are no errors - form is replaced by article html

Solution

Server will return piece of html that will replace part of page with article or form (with errors if needed). Actually this sentence is the most important part of this blog post. Implementation is very simple and straightforward.

Well actually the fact that you can return parts of html from server is also not new idea at all. It's just only now I finally understood that using this technique you can create more complicated things than modal window or tabs.

Implementation

views.py

def edit_new(request, new_id):
    new = get_object_or_404(MyModel, pk=new_id)
    if request.method == 'POST':
        form = NewsForm(request.POST, instance=new)
        if form.is_valid():
            new = form.save()
            return render_to_response('include/new.html', dict(new=new))
    else:
        form = NewsForm(instance=new)

    return render_to_response('include/form.html', dict(form=form, new=new))

form.html

This html will replace article block on 'edit' button click. Javascript should be moved to separate file of course.

<script type="text/javascript">
  function submitAndLoad(input) {
    $.ajax({
      url: "{% url edit_new new.id %}",
      data: $(input).parent().serialize(), // форма
      type: "post",
      dataType: "html",
      success: function(data) {
        $(input).parent().parent().html(data); // article block
      }
    });
    return false;
  };
</script>
<form>
  {{ form }}
  <input type="submit" value="Save" onclick="return submitAndLoad(this);"/>
</form>

news_list.html

<script type="text/javascript">
  function editNew(id) {
    $("#new-" + id).load("{% url edit_new new.id %}");
    return false;
  }
</script>

<!-- ... -->

<div id="new-{{ new.id }}">
  {% include "news/new.html" %}
</div>
<a onclick="return editNew({{ new.id }});" href="#">Edit</a>

Code can be cleaned up of course, I just wanted to show the idea.

Update

I'm translating this article almost five years after it was originally written and of course now it seems very childish :) Now we have angular and ajax forms are implemented a little differently. Still this old solution is not all that bad. I'd still replace one thing here - it's better to return json with html from server instead of just html.

Subscribe for the news and updates

More thoughts
Aug 25, 2017Technology
How to Upload Files With Django

File upload works differently from simple form inputs, which can be somewhat troublesome for beginners. Here I'll show you how to handle uploads with ease.

May 22, 2017Technology
Web Application Security: 10 Best Practices

Protection of WEB App is of paramount importance and it should be afforded the same level of security as the intellectual rights or private property. I'm going to cover how to protect your web app.

Mar 12, 2017Technology
Creating a chat with Django Channels

Nowadays, when every second large company has developed its own instant messenger, in the era of iMessages, Slack, Hipchat, Messager, Google Allo, Zulip and others, I will tell you how to keep up with the trend and write your own chat, using django-channels 0.17.3, django 1.10.x, python 3.5.x.

Oct 11, 2010Technology
Char search in Emacs as in Vim

In VIM there is a command for char search: f. After first use it can be repeated with ;. I like to navigate in line with it. You see that you need to go to bracket in a middle of a line - you press f( and one-two ; and you are there. There's no such command in Emacs, so I had to write my own. I've managed even to implement repetition with ;.

May 12, 2010Technology
Twitter API, OAuth and decorators

In my current project I had a task to use twitter API. Twitter uses OAuth for authentication, which is pretty dreary. To avoid fiddling with it all the time, I've moved authentication to decorator. If key is available - nothing happens, just view is launched as usual. It's convenient that there's no need for additional twitter settings in user profile. Code is in article.

Feb 18, 2010Technology
User profiles with inheritance in Django

Usually users' profiles are stored in single model. When there are multiple user types, separation is made by some field like user_type.Situation is a little more complicated when different data is needed for each user type.In this article I'll describe how I solve this task.