Jj's web stream

Generating Javascript Widgets with reversed URL endpoints in Django

I just read Elf Stenberg's solution on how to serve static Javascript with reversed URLs in Django, I was going to leave this as a comment but I better explain it here :P

When developing Django Widgets that require Javascript interaction with the server (Ajax, XHR, etc... ), you want your widget seamlessly deployable and have it know where to find its information (the endpoint).

Elf's solution is pretty interesting, as he runs the static fles through the Django Template renderer and stores the expanded versions for deployment. This is nice, but :

  • You have to re-render all the files if you change the endpoint

  • You have to re-render if you use the widget somewhere else (different proyect).

  • It becomes difficult to have an URL with parameters like a model Id or any variable (since there's no context).

What I do is add the URL to the Widget and set it as a document javascript variable, then use that variable on my .js

It goes something like this:

class MyWidget(forms.Widget):
  def __init__(self, endpoing, *args, **kwargs):
    self.endpoint = endpoint
    super(self, MyWidget).__init__(*args, **kwargs)

  def render(self):
    output = super(self, MyWidget).render()
    output =+ '<script>var WIDGET_ENDPOINT = "%s";</script%gt;' % self.endpoint

  class Media:
    js = ('my_widget.js',)

So you can just use django.core.urlresolvers.reverse to your endpoint when defining the widget :) .

On the template just render the field and add the {{form.media}} (at the bottom fo the document where scripts belong).

In your .js file:

$.getJSON(WIDGET_ENDPOINT, {}, function(resp) {
   $("#somenode").html(resp.results);
});

The downside is that you have to have that SCRIPT tag in the middle of your document, but really.. its only to ser a variable so it doesn't hurt much.

This is similar to this solution on accessing MEDIA_URL in Javascript files.

Comments

Elf Sternberg: On the other hand, I've made peace with having short snippets of <script> in my code, mostly to invoke The Digg technique.