DRY URLs in Django Javascript

2019-03-08 07:26发布

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 applying this to my client-side javascript. There is a JS class that loads some data depending on a passed-in ID. Is there a standard way to not-hardcode the URL that this data should come from?

var rq = new Request.HTML({
    'update':this.element,
}).get('/template/'+template_id+'/preview'); //The part that bothers me.

9条回答
来,给爷笑一个
2楼-- · 2019-03-08 07:48

One of the solutions I came with is to generate urls on backend and pass them to browser somehow.

It may not be suitable in every case, but I have a table (populated with AJAX) and clicking on a row should take the user to the single entry from this table.

(I am using django-restframework and Datatables).

Each entry from AJAX has the url attached:

class MyObjectSerializer(serializers.ModelSerializer):
    url = SerializerMethodField()
    # other elements

    def get_url(self, obj):
       return reverse("get_my_object", args=(obj.id,))

on loading ajax each url is attached as data attribute to row:

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

and on click we use this data attribute for url:

table.on( 'click', 'tbody tr', function () {
  window.location.href = $(this).data("url");
} );
查看更多
冷血范
3楼-- · 2019-03-08 07:54

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

查看更多
我命由我不由天
4楼-- · 2019-03-08 07:58

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

查看更多
登录 后发表回答