[Django]-Django apps using class-based views and ajax?

11👍

An ajax view isn’t much different to a normal view except that you usually want to return a different format then when processing a normal request. This format is usually JSON.

The documentation has an example of a mixin that can be used to return JSON, so this is a good starting point:

https://docs.djangoproject.com/en/dev/topics/class-based-views/mixins/#more-than-just-html

Do you want your view to reply to normal requests or only deal with AJAX requests? If the former, the only trick would be to write in a small check in the render_to_response method to reject any normal GET requests. If the latter, the above link goes on to discuss a situation where you can create a view that will deal with ajax requests and with normal requests.

13👍

without using the popular dajaxic and dajax packages, its still a straightforward affair.

It would help to write a decorator that just wraps around django’s is_ajax() function for request objects like so:

def ajax_request(function):
    def wrapper(request, *args, **kwargs):
        if not request.is_ajax():
            return render_to_response('error/ajax_required.html', {},
                context_instance=RequestContext(request))
        else:
            return function(request, *args, **kwargs)
    return wrapper

assuming there is a template called ajax_required to handle this particular failure. Something like this prevents a user from entering your ajax specific url in the browser if thats what you don’t want.

Because it makes for a shorter example, the following is a class based ajax view that renders a template.

from django.views.generic.base import TemplateView

class AjaxGeneral(TemplateView):
    template_name= None
    def get(self, request):
        data={}
        return render_to_response(self.template_name, data,
            context_instance=RequestContext(request))

    @method_decorator(ajax_request)
    def dispatch(self, *args, **kwargs):
        return super(AjaxGeneral, self).dispatch(*args, **kwargs)

now for everything ajax that just needs to render an html snippet you can define short class based views like:

class ShowSomeTable(AjaxGeneral):
    template_name="some_table.html"

Assuming some_table.html has some html snippet in it.

Now your urls.py entry for this view will look like:

url(r'showtable/$', ShowSomeTable.as_view()),

and you can call it in the js as normal like:

$(#dynamic-content).load('/showtable');
👤yassi

7👍

If you want to support both AJAX and traditional views, you can add something like this to your CreateView:

# at top of file
from django.http import JsonResponse  

# inside CreateView class
def render_to_response(self, context, **response_kwargs):
    """ Allow AJAX requests to be handled more gracefully """
    if self.request.is_ajax():
        return JsonResponse('Success',safe=False, **response_kwargs)
    else:
        return super(CreateView,self).render_to_response(context, **response_kwargs)

This handles regular views normally (with redirect etc.) but for AJAX, it return a JsonResponse instead. Where it returns ‘Success’, you may want to add more sophisticated logic but this is the basic idea.

Leave a comment