{"id":751,"date":"2012-08-11T14:41:17","date_gmt":"2012-08-11T18:41:17","guid":{"rendered":"http:\/\/blogs.law.harvard.edu\/jreyes\/?p=751"},"modified":"2012-08-11T14:41:17","modified_gmt":"2012-08-11T18:41:17","slug":"populate-urls-in-your-javascript-with-django","status":"publish","type":"post","link":"https:\/\/archive.blogs.harvard.edu\/jreyes\/2012\/08\/11\/populate-urls-in-your-javascript-with-django\/","title":{"rendered":"Populate URLs in Your Javascript with Django"},"content":{"rendered":"<p>All this Olympics has inspired me. I&#8217;ve decided to train for the summer games in Rio and to pursue my hobbies in full force. The former requires me to learn to kayak; the latter, to program, program, program.<\/p>\n<p>I&#8217;m building a fun web-app game on top of <a href=\"https:\/\/www.djangoproject.com\/\" title=\"Django\">Django<\/a>. And I want to make it dance with a little Javascript. I really like that I can look up the URLs of my pages by an internal name in templates using the <code>{% url %}<\/code> tag, but unfortunately that functionality isn&#8217;t available to me inside my static media&mdash;particularly, I&#8217;d like to be able to reverse look-up URLs in my site&#8217;s javascript, but I don&#8217;t want to have to render the file each time it gets served.<\/p>\n<p>After hunting around for a while, I figured, &#8220;Why not just render to Javascript once, fill in all the links, and be done with it?&#8221; So that&#8217;s what I did. And it doesn&#8217;t take much.<\/p>\n<p>I wrote a <a href=\"https:\/\/docs.djangoproject.com\/en\/dev\/howto\/custom-management-commands\/\" title=\"custom command\">custom command<\/a> called <code>populate_urls<\/code> that consumes a template (in this case, my Javascript) and spits out the finished product with all the holes filled in by Django and its handy URL resolvers. Then I stash its output in my static directory and pretend the whole thing never happened.<\/p>\n<p>from __future__ import print_function<\/p>\n<p>import sys<\/p>\n<p>from django.core.management.base import BaseCommand<br \/>\nfrom django.template import Template, Context<\/p>\n<p>class Command(BaseCommand):<br \/>\nfrom __future__ import print_function<\/p>\n<p>import sys<\/p>\n<p>from django.core.management.base import BaseCommand, CommandError<br \/>\nfrom django.template import Template, Context<\/p>\n<p>class Command(BaseCommand):<br \/>\n  args = &#8216;<input.template> <output.ext>&#8216;<br \/>\n  help = &#8216;Populates the URLs in the template. If no output filename is supplied, renders the template to standard out.&#8217;<br \/>\n  traceback = True<\/p>\n<p>  def handle(self, *args, **options):<br \/>\n    if len(args) < 1:\n      raise CommandError(\"You must supply a template.\")\n\n    with open(args[0], 'r') as templatefile:\n      template = Template(templatefile.read())\n      context = Context()\n\n    with sys.stdout if len(args) < 2 else open(args[1], 'w') as output:\n      print(template.render(context), file=output)\n[\/sourcecode]\n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>All this Olympics has inspired me. I&#8217;ve decided to train for the summer games in Rio and to pursue my hobbies in full force. The former requires me to learn to kayak; the latter, to program, program, program. I&#8217;m building &hellip; <a href=\"https:\/\/archive.blogs.harvard.edu\/jreyes\/2012\/08\/11\/populate-urls-in-your-javascript-with-django\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":102,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[380,142],"tags":[],"class_list":["post-751","post","type-post","status-publish","format-standard","hentry","category-computer-science","category-technology"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/archive.blogs.harvard.edu\/jreyes\/wp-json\/wp\/v2\/posts\/751","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/archive.blogs.harvard.edu\/jreyes\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/archive.blogs.harvard.edu\/jreyes\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/archive.blogs.harvard.edu\/jreyes\/wp-json\/wp\/v2\/users\/102"}],"replies":[{"embeddable":true,"href":"https:\/\/archive.blogs.harvard.edu\/jreyes\/wp-json\/wp\/v2\/comments?post=751"}],"version-history":[{"count":5,"href":"https:\/\/archive.blogs.harvard.edu\/jreyes\/wp-json\/wp\/v2\/posts\/751\/revisions"}],"predecessor-version":[{"id":756,"href":"https:\/\/archive.blogs.harvard.edu\/jreyes\/wp-json\/wp\/v2\/posts\/751\/revisions\/756"}],"wp:attachment":[{"href":"https:\/\/archive.blogs.harvard.edu\/jreyes\/wp-json\/wp\/v2\/media?parent=751"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/archive.blogs.harvard.edu\/jreyes\/wp-json\/wp\/v2\/categories?post=751"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/archive.blogs.harvard.edu\/jreyes\/wp-json\/wp\/v2\/tags?post=751"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}