Dry URLs in Django Javascript

I am using Django in Appengine. I use the django reverse() function everywhere, keeping everything as dry as possible.

However, I am having problems using this client side JavaScript code. There is a JS class that loads some data depending on the ID of the passed. Is there a standard way for non-hardcode URLs from which this data should come from?

 var rq = new Request.HTML({ 'update':this.element, }).get('/template/'+template_id+'/preview'); //The part that bothers me. 
+47
javascript google-app-engine ajax django dry
Apr 27 '10 at 19:30
source share
9 answers

The most sensible solution is to list the URLs in the JavaScript file and have the JavaScript equivalent () () on the client. The only objection may be that the entire structure of the URL is disclosed.

Here is a function (from this question ).

+8
07 Oct 2018-11-21T00:
source share

There is another method that does not require revealing the entire structure of url or ajax requests to resolve each URL. Although it's not very pretty, it just hits the rest:

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

( blog_view_post URLs do not have to contain magic number 999 ).

+28
Jun 29 2018-12-12T00:
source share

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

In my case, I wanted the external JS script to make an AJAX call when the button was clicked (after doing another processing).

In HTML, I used the custom attribute HTML-5, thereby

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

Then in javascript just did

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

This meant that the Django template system followed all the reverse() logic for me.

+7
Jun 02 '16 at 17:16
source share

It's good to assume that all parameters from JavaScript to Django will be passed as request.GET or request.POST. You can do this in most cases because you do not need good formatted URLs for JavaScript requests.

Then the only problem is to pass the url from Django to JavaScript. I published a library for this. Code example:

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' }, }); 
+4
Apr 15 '12 at 11:01
source share

Like Anatoly, answer, but a little more flexible. 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 several times.

+4
Sep 14
source share

I like the idea of ​​Anatoly, but I think using a certain integer is dangerous. Usually I want to specify the name of an id object, which should always be positive, so I just use negative integers as placeholders. Does this mean adding -? to a URL definition, for example:

 url(r'^events/(?P<event_id>-?\d+)/$', events.views.event_details), 

Then I can get the reverse url in the template by writing

 {% url 'events.views.event_details' event_id=-1 %} 

And use replace in javascript to replace placeholder -1 , so in the template I would write something like

 <script type="text/javascript"> var actual_event_id = 123; var url = "{% url 'events.views.event_details' event_id=-1 %}".replace('-1', actual_event_id); </script> 

This easily extends to several arguments, and the mapping for a particular argument is visible directly in the template.

+2
Oct 23 '13 at 15:12
source share

I have found a simple trick for you. If your url looks like this:

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

and you want to cancel in JS without actually providing the material (delaying the execution time of JS to provide it) - you can do the following:

Change the view to give the parameter a default value of none and process it, responding with an error if it is not set:

views.py

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

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

The generated template should have a URL without a parameter in JS, and in JS you can simply concatenate by parameters (s).

+1
Jan 29 '13 at 16:38
source share

One of the solutions I came up with is to create URLs to the backend and somehow pass them to the browser.

It may not be suitable in each case, but I have a table (filled with AJAX), and clicking on a row should bring the user to a single record from this table.

(I use django-restframework and Datatables ).

Each AJAX entry has an attached URL:

 class MyObjectSerializer(serializers.ModelSerializer): url = SerializerMethodField() # other elements def get_url(self, obj): return reverse("get_my_object", args=(obj.id,)) 

when loading ajax, each url is bound as a data attribute to a string:

 var table = $('#my-table').DataTable({ createdRow: function ( row, data, index ) { $(row).data("url", data["url"]) } }); 

and when clicked, we use this data attribute for the URL:

 table.on( 'click', 'tbody tr', function () { window.location.href = $(this).data("url"); } ); 
0
Feb 11 '16 at 13:46 on
source share

Use this package: https://github.com/ierror/django-js-reverse

You will have an object in your JS with all the urls defined in django. This is the best approach I've found so far.

The only thing you need to do is add the created js to the head of the base template and run the control command to update the generated js every time you add the url

0
Nov 29 '17 at 21:46
source share



All Articles