views:

187

answers:

3

I'm trying to output in bibtex format in Django and the template looks like this:

@{{ pubentry.type }{,
  author    = {{% for author in pubentry.authors.all %}{{ author.first_name }} {{ author.middle_name }} {{ author.last_name }}{% if not forloop.last %} and {% endif %}
              {% endfor %}},
  title     = {{{ pubentry.title }}},
  journal   = {{{ pubentry.journal }}}
}

The problem is with the "{{{" or "{{%". One way to go around the problem is to add a space after the first "{", but that kind of tamper the format. What's the right way to escape { in Django templates?

+8  A: 

Have a look at the templatetag tag:

Output one of the syntax characters used to compose template tags.

Since the template system has no concept of "escaping", to display one of the bits used in template tags, you must use the {% templatetag %} tag.

What you are after is:

{% templatetag openvariable %}

Maybe there is a nicer solution because this does not increase readability...

Felix Kling
+1  A: 

With the templatetag template tag.

title     = {% templatetag openvariable %}{% templatetag openbrace %} pubentry.title {% templatetag closevariable %}{% templatetag closebrace %},
Ignacio Vazquez-Abrams
+1  A: 

Another (more flexible) approach may be to convert the values to a bibtex-like value before sending them to your template. You'll probably need to do this anyway to escape some of the characters that bibtex/latex can't handle. Here's something similar I prepared earlier:

import datetime

class BibTeXString(unicode):
  pass

def bibtex_repr(obj):
  """ A version of the string repr method, that always outputs variables suitable for BibTeX. """
  # If this has already been processed, it's ok
  if isinstance(obj, BibTeXString):
    return obj
  # Translate strings
  if isinstance(obj, basestring):
    value = unicode(obj).translate(CHAR_ESCAPES).strip()
    return BibTeXString('{%s}' % value)
  # Dates
  elif isinstance(obj, datetime.date):
    return BibTeXString('{%02d-%02d-%02d}' % (obj.year, obj.month, obj.day))
  # Integers
  if isinstance(obj, (int, long)):
    return BibTeXString(str(obj))
  else:
    return BibTeXString(repr(obj))


CHAR_ESCAPES = {
  ord(u'$'): u'\\$',
  ord(u'&'): u'\\&',
  ord(u'%'): u'\\%',
  ord(u'#'): u'\\#',
  ord(u'_'): u'\\_',
  ord(u'\u2018'): u'`',
  ord(u'\u2019'): u"'", 
  ord(u'\u201c'): u"``", 
  ord(u'\u201d'): u"''" ,
  ord(u'\u2014'): u'---', 
  ord(u'\u2013'): u'--',
}

You could even use this as a template filter if you wanted, making your template look like:

@{{ pubentry.type }{,
  author    = {% filter bibtex %}{% for author in pubentry.authors.all %}{{ author.first_name }} {{ author.middle_name }} {{ author.last_name }}{% if not forloop.last %} and {% endif %}{% endfor %}}{% endfilter %},
  title     = {{ pubentry.title|bibtex }},
  journal   = {{ pubentry.journal|bibtex }}
}

But I would escape the content before it gets to the template, so that your template just needs to do this:

@{{ pubentry.type }{,
  {% for field in fields %}{{ field }}{% if not forloop.last %},{% endif %}{% endfor %}
}

Or even leave out the template altogether at this stage. Good luck!

Will Hardy
Thanks! Sounds interesting - I am still learning Django/Python (8 hrs of exp so far) but I will look into this.
rxin