Calling Django `reverse` in client-side Javascript

Solution 1:

There is another method, which doesn't require exposing the entire url structure or ajax requests for resolving each url. While it's not really beautiful, it beats the others with simplicity:

var url = '{% url blog_view_post 999 %}'.replace (999, post_id);

(blog_view_post urls must not contain the magic 999 number themselves of course.)

Solution 2:

Having just struggled with this, I came up with a slightly different solution.

In my case, I wanted an external JS script to invoke an AJAX call on a button click (after doing some other processing).

In the HTML, I used an HTML-5 custom attribute thus

<button ... id="test-button" data-ajax-target="{% url 'named-url' %}">

Then, in the javascript, simply did

$.post($("#test-button").attr("data-ajax-target"), ... );

Which meant Django's template system did all the reverse() logic for me.

Solution 3:

The most reasonable solution seems to be passing a list of URLs in a JavaScript file, and having a JavaScript equivalent of reverse() available on the client. The only objection might be that the entire URL structure is exposed.

Here is such a function (from this question).

Solution 4:

Good thing is to assume that all parameters from JavaScript to Django will be passed as request.GET or request.POST. You can do that in most cases, because you don't need nice formatted urls for JavaScript queries.

Then only problem is to pass url from Django to JavaScript. I have published library for that. Example code:

urls.py

def javascript_settings():
    return {
        'template_preview_url': reverse('template-preview'),
    }

javascript

$.ajax({
  type: 'POST',
  url: configuration['my_rendering_app']['template_preview_url'],
  data: { template: 'foo.html' },
});

Solution 5:

Similar to Anatoly's answer, but a little more flexible. Put at the top of the page:

<script type="text/javascript">
window.myviewURL = '{% url myview foobar %}';
</script>

Then you can do something like

url = window.myviewURL.replace('foobar','my_id');

or whatever. If your url contains multiple variables just run the replace method multiple times.