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 18, 2022Technology
5 Best Practices of RESTful API Design to Keep Your Users Happy

Dive into our guide to RESTful API best practices

May 9, 2018Technology
How to Generate PDF Files in Python with Xhtml2pdf, WeasyPrint or Unoconv

Programmatic generation of PDF files is a frequent task when developing applications that can export reports, bills, or questionnaires. In this article, we will consider three common tools for creating PDFs, including their installation and converting principles.

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.

Aug 8, 2016TechnologyBusiness
How To Add HTML5 Geolocation To Your Web App?

In this article I will describe how to integrate geolocation HTML5 function to a web app so you can then easily implement it in your apps or websites. As an example we are going to create small web app which will be able to calculate the shortest route between detected user’s location and predefined destination using Google Maps API.

Sep 23, 2010Technology
Dynamic class generation, QuerySetManager and use_for_related_fields

It appears that not everyone knows that in python you can create classes dynamically without metaclasses. I'll show an example of how to do it.So we've learned how to use custom QuerySet to chain requests:Article.objects.old().public()Now we need to make it work for related objects:user.articles.old().public()This is done using use_for_related_fields, but it needs a little trick.

Feb 18, 2010Technology
Business logic in models

In my recent project there was a lot of data business logic, so I had to organize this code somehow. In this article I'll describe a few hints on how to it.