Services Blog Français

Django & ajax: how to reverse urls in javascript (not)

| by jpic | ajax django http api

IMPORTANT UPDATE: the approach proposed in this article is bad. Read this one instead.

You can start building a user interface using Django’s awesome CRUD in a matter of seconds, for example with just this server side configuration:

    url(delete/(?P<pk>\d+)/$', 
        generic.DeleteView.as_view(model=YourModel),
        name='yourapp_yourmodel_delete'),

It doesn’t matter how long you’ve been using Django, this kind of trick is always charming. When you have a deadline, you know you can get Django out of the way in a single line of code, and work on the templates.

A rich user interface might need to work with many Django views. It might even need to reverse urls like yourapp_yourmodel_delete, which take an argument in the regexp…

Current solutions

  • django-js-utils allows reversing urls from javascript, but requires to expose urls to everybody,
  • it is also possible create a reverse view which javascript should call, but it requires one ajax request to generate a url.
  • another user suggested that this same reverse view could respond directly with the result of the url, which might be a good idea after all.

Working around having to reverse the regexp

A quick and easy way to do clear the way is to use the PkUrlKwarg mixin:

    class PkUrlKwarg(SingleObjectMixin):
        """
        Take the pk from request.GET or request.POST and sets it to kwargs,
        useful to avoid fun reversing urls from javascript
        """
        def get_object(self, queryset=None):
            self.kwargs[self.pk_url_kwarg] = self.request.REQUEST['pk']
            return super(PkUrlKwarg, self).get_object(queryset)

This will make /update/?pk=123 to behave like /update/123/, eliminating the need to reverse urls:

    # url
    url(r'tab/delete/$',
        login_required(TabDeleteView.as_view()),
        name='form_designer_tab_delete'),

    # view
    class TabDeleteView(PkUrlKwarg, TabSecurity, AjaxDeleteView):
        model = Tab

Blablablabla

Quite controversial isn’t it ?

Django users know very the importance of clean, usable urls. I myself know how to write many urls to directly access a resource I often need. And that never is an edit url - except side-wide configuration for example /configure/ which is also pretty simple and usable.

At most, there can be nice delete urls like this: /blog/your-blog/delete/. These kind of great urls are designed to be used by Humans, not by Javascript. Javascript just wants to make a standard XHTMLHttpRequest to the blog delete resource for blog pk=1234.

Conclusion

  • To be easily usable by Humans, your blog delete url should be: /blog/your-blog/delete/.
  • To be easily usable by Javascript, your blog delete url should by blogDeleteUrl + 'pk=1234'.

They trust us

Contact

logo