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:36

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' },
});
查看更多
看我几分像从前
3楼-- · 2019-03-08 07:36

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

You'll have an object in your JS with all the urls defined in django. It's the best approach I found so far.

The only thing you need to do is add the generated js in the head of your base template and run a management command to update the generated js everytime you add a url

查看更多
在下西门庆
4楼-- · 2019-03-08 07:37

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.

查看更多
贼婆χ
5楼-- · 2019-03-08 07:45

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.

查看更多
时光不老,我们不散
6楼-- · 2019-03-08 07:47

I like Anatoly's idea, but I think using a specific integer is dangerous. I typically want to specify an say an object id, which are always required to be positive, so I just use negative integers as placeholders. This means adding -? to the the url definition, like so:

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

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

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

And use replace in javascript to replace the placeholder -1, so that 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 multiple arguments too, and the mapping for a particular argument is visible directly in the template.

查看更多
老娘就宠你
7楼-- · 2019-03-08 07:48

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

查看更多
登录 后发表回答