As-You-Type Slug Uniqueness Validation
Welcome to the fourth and final entry in the Django, jQuery and Ajax tutorial series, which picks up where Layers of Authentication left off.
Because it's the last entry, we're going to do something quick and fun: make the frontpage's slug field validate slugs as you type, by changing the background color of the field to either red (in-use) or blue (available).
Let's get started.
Two Guys, A URL, and A View
First go ahead and open up notes/urls.py
and add this url:
(r'^slug_available/$', 'notes.views.slug_available'),
Then open notes/views.py
and add this method:
@login_required
def slug_available(request):
if request.method == "GET":
get = request.GET.copy()
if get.has_key('slug'):
slug_str = get['slug']
if Note.objects.filter(slug=slug_str).count() == 0:
return HttpResponse(slug_str)
else:
return HttpResponseServerError(slug_str)
return HttpResponseServerError("Requires a slug field.")
Often we use the data we return to indicate success or failure of a request, but it's easier, clearer, and (perhaps) truer to http to use response codes to distinguish between success and failure.
For this view, it will return a 200 response code (because
we're using HttpResponse
) for success, and a 500 reponse
code (because of HttpResponseServerError
) for failure.
We then distinguish between kinds of failure by varying the
text returned along with the 500 response code.
Other than that, slug_available
is pretty straight-forward,
so we'll move on to integrating the view into our templates.
Integrating into notes/note_list.html
We'll start our joyous integration with the list view,
so go ahead and open up the notes/note_list.html
template.
First, lets fix some of our earlier laziness, and wrap
everything in the <script></script>
tag in this code:
<script>
$(document).ready(function() {
// All other JavaScript here.
});
</script>
That is a useful jQuery pattern which makes sure your JavaScript loads after the DOM has settled down and is ready to be tampered with. Some really ambiguous and hard to track down issues can arise when you don't use it... so... use it.
Now on to our task at hand: updating the background color of the span input based on slug availability.
It'll look like this (which you'll need to add somewhere
within the <script></script>
tags in note_list.html
):
$("#slug").keyup(function() {
var slug = this.value;
var complete = function(res, status) {
if (status == "success") $("#slug").css('background-color','#A0A0FF');
else $("#slug").css('background-color','#FFA0A0');
}
$.ajax({type:'GET', url:'/slug_available/', data:{'slug': slug }, complete:complete});
});
});
If we wanted to, we could compress that a bit by inlining the first line.
$("#slug").keyup(function() {
var complete = function(res, status) {
if (status=="success") $("#slug").css('background-color','blue');
else $("#slug").css('background-color','red');
}
$.get('/slug_available/',{'slug':this.value},complete:complete);
});
Then we go inline the complete
function as well.
$("#slug").keyup(function() {
$.get('/slug_available/',{'slug':this.value},complete:function(res, status) {
if (status=="success") $("#slug").css('background-color','blue');
else $("#slug").css('background-color','red');
})});
Which seems like a good place to stop.
So with that we have an as-you-type validation system implemented for slugs. This is one Ajax technique that I find to be genuinely useful at conveying additional information to users, and highly recommend integrating into applications where it fits.
Download
You can access the code for this project at its GitHub repository.
(Although, you may have to rename the repository directory to ajax_tut
before it runs properly.)
Closing Down The Series
Well, that wraps up the Django, jQuery and Ajax tutorial series. Hopefully it was a bit helpful. I'll end by reiterating a brief warning: Ajax leads to a lot of really terribly user interfaces. Make sure that you're using Ajax because Ajax brings a real benefit, not just because you can.
Let me know where I've made mistakes, and I'll lumber around to correcting them as soon as life permits.