1.. _tutorials.gettingstarted.templates: 2 3Using Templates 4=============== 5HTML embedded in code is messy and difficult to maintain. It's better to use a 6templating system, where the HTML is kept in a separate file with special 7syntax to indicate where the data from the application appears. There are many 8templating systems for Python: EZT, Cheetah, ClearSilver, Quixote, and Django 9are just a few. You can use your template engine of choice by bundling it with 10your application code. 11 12For your convenience, the ``webapp2`` module includes Django's templating 13engine. Versions 1.2 and 0.96 are included with the SDK and are part of App 14Engine, so you do not need to bundle Django yourself to use it. 15 16See the Django section of `Third-party libraries <http://code.google.com/appengine/docs/python/tools/libraries.html#Django>`_ 17for information on using supported Django versions. 18 19 20Using Django Templates 21---------------------- 22Add the following import statements at the top of helloworld/helloworld.py:: 23 24 import os 25 from google.appengine.ext.webapp import template 26 27Replace the ``MainPage`` handler with code that resembles the following:: 28 29 class MainPage(webapp2.RequestHandler): 30 def get(self): 31 guestbook_name=self.request.get('guestbook_name') 32 greetings_query = Greeting.all().ancestor( 33 guestbook_key(guestbook_name)).order('-date') 34 greetings = greetings_query.fetch(10) 35 36 if users.get_current_user(): 37 url = users.create_logout_url(self.request.uri) 38 url_linktext = 'Logout' 39 else: 40 url = users.create_login_url(self.request.uri) 41 url_linktext = 'Login' 42 43 template_values = { 44 'greetings': greetings, 45 'url': url, 46 'url_linktext': url_linktext, 47 } 48 49 path = os.path.join(os.path.dirname(__file__), 'index.html') 50 self.response.out.write(template.render(path, template_values)) 51 52Finally, create a new file in the ``helloworld`` directory named ``index.html``, 53with the following contents: 54 55.. code-block:: html+django 56 57 <html> 58 <body> 59 {% for greeting in greetings %} 60 {% if greeting.author %} 61 <b>{{ greeting.author.nickname }}</b> wrote: 62 {% else %} 63 An anonymous person wrote: 64 {% endif %} 65 <blockquote>{{ greeting.content|escape }}</blockquote> 66 {% endfor %} 67 68 <form action="/sign" method="post"> 69 <div><textarea name="content" rows="3" cols="60"></textarea></div> 70 <div><input type="submit" value="Sign Guestbook"></div> 71 </form> 72 73 <a href="{{ url }}">{{ url_linktext }}</a> 74 </body> 75 </html> 76 77Reload the page, and try it out. 78 79``template.render(path, template_values)`` takes a file path to the template 80file and a dictionary of values, and returns the rendered text. The template 81uses Django templating syntax to access and iterate over the values, and can 82refer to properties of those values. In many cases, you can pass datastore 83model objects directly as values, and access their properties from templates. 84 85.. note:: 86 An App Engine application has read-only access to all of the files uploaded 87 with the project, the library modules, and no other files. The current 88 working directory is the application root directory, so the path to 89 ``index.html`` is simply ``"index.html"``. 90 91 92Next... 93------- 94Every web application returns dynamically generated HTML from the application 95code, via templates or some other mechanism. Most web applications also need 96to serve static content, such as images, CSS stylesheets, or JavaScript files. 97For efficiency, App Engine treats static files differently from application 98source and data files. You can use App Engine's static files feature to serve 99a CSS stylesheet for this application. 100 101Continue to :ref:`tutorials.gettingstarted.staticfiles`. 102