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 Djangos 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 its shipped with SDK. Amazingly, its 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 dont know if i18n will be this easy as well, I might do a follow-up later. I need to mention I didnt want to switch at first and still dont. 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 didnt know if there is one I forgot to filter, now I need to worry less. If you are sure some dont need, you just {{ varname|safe }} so Django wont escape it.

I dont 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)

Thats 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 couldnt get it to work. Few days ago, I read this question. It gave me an idea, though I cant 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 isnt 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 dont know why that name of capability didnt 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.