Recently, I upgraded SDK to 1.4.2 from 1.4.1 and added new stuff to lil.btn. I was trying to read the Django 0.96 template documentation on Django’s website, then I found out the page has been removed. Actually, I recalled I have known the removal of the page for some time.

1   Django 1.2.5 Template

Anyway, I decided to use Django 1.2.5 Template since it’s shipped with SDK. Amazingly, it’s so easy to switch to another version from the default version 0.96. This is what I only added before the template import, suggested by the doc,


# os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

from google.appengine.dist import use_library
use_library('django', '1.2')

from google.appengine.ext.webapp import template

I only use template. I don’t know if i18n will be this easy as well, I might do a follow-up later. I need to mention I didn’t want to switch at first and still don’t. But it seems that I have to.

1.1   autoescape

One thing about Django 1.2.5 I like is it automatically enables escaping for preventing code injection on client-side. You know developers sometimes are lazy or careless, because we think will review our codes once everything is settled. But one might be missed or even intentionally skipping reviewing some codes and forget there is always a risk.

When I was using 0.96, I often did {{ varname|striptags|escape }} or just {{ varname|escape }}. I didn’t know if there is one I forgot to filter, now I need to worry less. If you are sure some don’t need, you just {{ varname|safe }} so Django won’t escape it.

I don’t know which version it was started with, but it was commited into code three years ago.

1.2   Loading humanize

Probably two years ago, I wanted to add thousands separator to some statistic integer numbers. You can always do that in your Python code1.

I know there is a set of template filters called humanize in Django, why re-invent? I tried to include it into of my GAE app. I got the code from SDK and removed unwanted filters and put it in the top level of my source.

But I found out there is a really quick and easy way and it works for both 0.96 and 1.2 (1.2.5),


def main():

webapp.template.register_template_library('django.contrib.humanize.templatetags.humanize')
run_wsgi_app(application)

That’s it. You just use that register and there is no need for {% load humanize %} in your template, you just add the filters wherever you want, e.g. {{ varname|intcomma }}. I believe this also works on other contributed Django templating code sitting in /contrib.

When I firstly tried, I even added a Django setting file, but I couldn’t get it to work. Few days ago, I read this question. It gave me an idea, though I can’t just use import to get it work. I use that register function with full module path, that works.

[1]Coding by yourself or using Python 2.7+, but this isn’t the case for Google App Engine. But may be some day, supporting 2.7 is listed in roadmap.

2   Capability name of datastore for CapabilitySet

I read the documentation about the supported capabilities and I had these


CapabilitySet('datastore').is_enabled()
CapabilitySet('datastore_write').is_enabled()
CapabilitySet('memcache').is_enabled()

They run fine on development server, however, after I deployed the code, I got:


Traceback (most recent call last):
File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/webapp/__init__.py", line 515, in __call__
handler.get(*groups)
File "/base/data/home/apps/lilbtn/1.348320236448169656/itchape.py", line 205, in get
if CapabilitySet('datastore').is_enabled():
File "/base/python_runtime/python_lib/versions/1/google/appengine/api/capabilities/__init__.py", line 98, in is_enabled
config = self._get_status()
File "/base/python_runtime/python_lib/versions/1/google/appengine/api/capabilities/__init__.py", line 170, in _get_status
raise UnknownCapabilityError()
UnknownCapabilityError

The memory cache part is fine. I don’t know why that name of capability didn’t work, but I found an alternates,


db.READ_CAPABILITY
db.WRITE_CAPABILITY

But I use these later,


CapabilitySet('datastore_v3', capabilities=['read']).is_enabled()
CapabilitySet('datastore_v3', capabilities=['write']).is_enabled()

I found the second line on Handling downtime: The capabilities API and testing, which I had skimmed when it was published.