Calling Django `reverse` in client-side Javascript

前端 未结 10 488
无人共我
无人共我 2020-12-13 02:22

I\'m using Django on Appengine. I\'m using the django reverse() function everywhere, keeping everything as DRY as possible.

However, I\'m having trouble

相关标签:
10条回答
  • I always use strings as opposed to integers in configuring urls, i.e. instead of something like

    ... r'^something/(?P<first_integer_parameter>\d+)/something_else/(?P<second_integer_parameter>\d+)/' ...
    

    e.g: something/911/something_else/8/

    I would replace 'd' for integers with 'w' for strings like so ...

    ... r'^something/(?P<first_integer_parameter>\w+)/something_else/(?P<second_integer_parameter>\w+)/' ...
    

    Then, in javascript I can put strings as placeholders and the django template engine will not complain either:

    ...
    var url     = `{% url 'myapiname:urlname' 'xxz' 'xxy' %}?first_kwarg=${first_kwarg_value}&second_kwarg=${second_kwarg_value}`.replace('xxz',first_integer_paramater_value).replace('xxy', second_integer_parameter_value);
    
            var x = new L.GeoJSON.AJAX(url, {
                style: function(feature){ 
    ...
    

    and the url will remain the same, i.e something/911/something_else/8/. This way you avoid the integer parameters replacement issue as string placeholders (a,b,c,d,...z) are not expected in as parameters

    0 讨论(0)
  • 2020-12-13 02:50

    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.

    0 讨论(0)
  • 2020-12-13 02:50

    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' },
    });
    
    0 讨论(0)
  • 2020-12-13 02:52

    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).

    0 讨论(0)
  • 2020-12-13 02:52

    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.

    0 讨论(0)
  • 2020-12-13 02:53

    I've found a simple trick for this. If your url is a pattern like:

    "xyz/(?P<stuff>.*)$"
    

    and you want to reverse in the JS without actually providing stuff (deferring to the JS run time to provide this) - you can do the following:

    Alter the view to give the parameter a default value - of none, and handle that by responding with an error if its not set:

    views.py

    def xzy(stuff=None):
      if not stuff:
        raise Http404
      ... < rest of the view code> ...
    
    • Alter the URL match to make the parameter optional: "xyz/(?P<stuff>.*)?$"
    • And in the template js code:

      .ajax({ url: "{{ url views.xyz }}" + js_stuff, ... ... })

    The generated template should then have the URL without the parameter in the JS, and in the JS you can simply concatenate on the parameter(s).

    0 讨论(0)
提交回复
热议问题