thirdparty/google_appengine/google/appengine/ext/webapp/template.py
changeset 109 620f9b141567
child 686 df109be0567c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thirdparty/google_appengine/google/appengine/ext/webapp/template.py	Tue Aug 26 21:49:54 2008 +0000
@@ -0,0 +1,219 @@
+#!/usr/bin/env python
+#
+# Copyright 2007 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""A simple wrapper for Django templates.
+
+The main purpose of this module is to hide all of the package import pain
+you normally have to go through to get Django to work. We expose the Django
+Template and Context classes from this module, handling the import nonsense
+on behalf of clients.
+
+Typical usage:
+
+   from google.appengine.ext.webapp import template
+   print template.render('templates/index.html', {'foo': 'bar'})
+
+Django uses a global setting for the directory in which it looks for templates.
+This is not natural in the context of the webapp module, so our load method
+takes in a complete template path, and we set these settings on the fly
+automatically.  Because we have to set and use a global setting on every
+method call, this module is not thread safe, though that is not an issue
+for applications.
+
+Django template documentation is available at:
+http://www.djangoproject.com/documentation/templates/
+"""
+
+
+
+
+
+import md5
+import os
+
+try:
+  from django import v0_96
+except ImportError:
+  pass
+import django
+
+import django.conf
+try:
+  django.conf.settings.configure(
+    DEBUG=False,
+    TEMPLATE_DEBUG=False,
+    TEMPLATE_LOADERS=(
+      'django.template.loaders.filesystem.load_template_source',
+    ),
+  )
+except (EnvironmentError, RuntimeError):
+  pass
+import django.template
+import django.template.loader
+
+from google.appengine.ext import webapp
+
+def render(template_path, template_dict, debug=False):
+  """Renders the template at the given path with the given dict of values.
+
+  Example usage:
+    render("templates/index.html", {"name": "Bret", "values": [1, 2, 3]})
+
+  Args:
+    template_path: path to a Django template
+    template_dict: dictionary of values to apply to the template
+  """
+  t = load(template_path, debug)
+  return t.render(Context(template_dict))
+
+
+template_cache = {}
+def load(path, debug=False):
+  """Loads the Django template from the given path.
+
+  It is better to use this function than to construct a Template using the
+  class below because Django requires you to load the template with a method
+  if you want imports and extends to work in the template.
+  """
+  abspath = os.path.abspath(path)
+
+  if not debug:
+    template = template_cache.get(abspath, None)
+  else:
+    template = None
+
+  if not template:
+    directory, file_name = os.path.split(abspath)
+    new_settings = {
+        'TEMPLATE_DIRS': (directory,),
+        'TEMPLATE_DEBUG': debug,
+        'DEBUG': debug,
+        }
+    old_settings = _swap_settings(new_settings)
+    try:
+      template = django.template.loader.get_template(file_name)
+    finally:
+      _swap_settings(old_settings)
+
+    if not debug:
+      template_cache[abspath] = template
+
+    def wrap_render(context, orig_render=template.render):
+      URLNode = django.template.defaulttags.URLNode
+      save_urlnode_render = URLNode.render
+      old_settings = _swap_settings(new_settings)
+      try:
+        URLNode.render = _urlnode_render_replacement
+        return orig_render(context)
+      finally:
+        _swap_settings(old_settings)
+        URLNode.render = save_urlnode_render
+
+    template.render = wrap_render
+
+  return template
+
+
+def _swap_settings(new):
+  """Swap in selected Django settings, returning old settings.
+
+  Example:
+    save = _swap_settings({'X': 1, 'Y': 2})
+    try:
+      ...new settings for X and Y are in effect here...
+    finally:
+      _swap_settings(save)
+
+  Args:
+    new: A dict containing settings to change; the keys should
+      be setting names and the values settings values.
+
+  Returns:
+    Another dict structured the same was as the argument containing
+    the original settings.  Original settings that were not set at all
+    are returned as None, and will be restored as None by the
+    'finally' clause in the example above.  This shouldn't matter; we
+    can't delete settings that are given as None, since None is also a
+    legitimate value for some settings.  Creating a separate flag value
+    for 'unset' settings seems overkill as there is no known use case.
+  """
+  settings = django.conf.settings
+  old = {}
+  for key, value in new.iteritems():
+    old[key] = getattr(settings, key, None)
+    setattr(settings, key, value)
+  return old
+
+
+def create_template_register():
+  """Used to extend the Django template library with custom filters and tags.
+
+  To extend the template library with a custom filter module, create a Python
+  module, and create a module-level variable named "register", and register
+  all custom filters to it as described at
+  http://www.djangoproject.com/documentation/templates_python/
+    #extending-the-template-system:
+
+    templatefilters.py
+    ==================
+    register = webapp.template.create_template_register()
+
+    def cut(value, arg):
+      return value.replace(arg, '')
+    register.filter(cut)
+
+  Then, register the custom template module with the register_template_module
+  function below in your application module:
+
+    myapp.py
+    ========
+    webapp.template.register_template_module('templatefilters')
+  """
+  return django.template.Library()
+
+
+def register_template_library(package_name):
+  """Registers a template extension module to make it usable in templates.
+
+  See the documentation for create_template_register for more information."""
+  if not django.template.libraries.get(package_name, None):
+    django.template.add_to_builtins(package_name)
+
+
+Template = django.template.Template
+Context = django.template.Context
+
+
+def _urlnode_render_replacement(self, context):
+  """Replacement for django's {% url %} block.
+
+  This version uses WSGIApplication's url mapping to create urls.
+
+  Examples:
+
+  <a href="{% url MyPageHandler "overview" %}">
+  {% url MyPageHandler implicit_args=False %}
+  {% url MyPageHandler "calendar" %}
+  {% url MyPageHandler "jsmith","calendar" %}
+  """
+  args = [arg.resolve(context) for arg in self.args]
+  try:
+    app = webapp.WSGIApplication.active_instance
+    handler = app.get_registered_handler_by_name(self.view_name)
+    return handler.get_url(implicit_args=True, *args)
+  except webapp.NoUrlFoundError:
+    return ''