1TODO: documentation 2=================== 3Miscelaneous notes abotu things to be documented. 4 5Unordered list of topics to be documented 6----------------------------------------- 7- routing 8 9 - common regular expressions examples 10 11- sessions 12 13 - basic usage & configuration 14 - using multiple sessions in the same request 15 - using different backends 16 - using flashes 17 - updating session arguments (max_age etc) 18 - purging db sessions 19 20- i18n (increment existing tutorial) 21 22 - basic usage & configuration 23 - loading locale/timezone automatically for each request 24 - formatting date/time/datetime 25 - formatting currency 26 - using i18n in templates 27 28- jinja2 & mako 29 30 - basic usage & configuration 31 - setting global filters and variables (using config or factory) 32 33- auth 34 35 - basic usage & configuration 36 - setting up 'own auth' 37 - making user available automatically on each request 38 - purging tokens 39 40- config 41 42 - configuration conventions ("namespaced" configuration for webapp2_extras 43 modules) 44 45- tricks 46 47 - configuration in a separate file 48 - routes in a separate file 49 - reduce verbosity when defining routes (R = webapp2.Route) 50 51Common errors 52------------- 53- "TypeError: 'unicode' object is not callable": one possible reason is that 54 the ``RequestHandler`` returned a string. If the handler returns anything, it 55 **must** be a :class:`webapp2.Response` object. Or it must not return 56 anything and write to the response instead using ``self.response.write()``. 57 58Secret keys 59----------- 60Add a note about how to generate strong session secret keys:: 61 62 $ openssl genrsa -out ${PWD}/private_rsa_key.pem 2048 63 64Jinja2 factory 65-------------- 66To create Jinja2 with custom filters and global variables:: 67 68 from webapp2_extras import jinja2 69 70 def jinja2_factory(app): 71 j = jinja2.Jinja2(app) 72 j.environment.filters.update({ 73 'my_filter': my_filter, 74 }) 75 j.environment.globals.update({ 76 'my_global': my_global, 77 }) 78 return j 79 80 # When you need jinja, get it passing the factory. 81 j = jinja2.get_jinja2(factory=jinja2_factory) 82 83Debugging Jinja2 84---------------- 85http://stackoverflow.com/questions/3086091/debug-jinja2-in-google-app-engine/3694434#3694434 86 87Configuration notes 88------------------- 89Notice that configuration is set primarily in the application. See: 90 91 http://webapp-improved.appspot.com/guide/app.html#config 92 93By convention, modules that are configurable in webapp2 use the module 94name as key, to avoid name clashes. Their configuration is then set in 95a nested dict. So, e.g., i18n, jinja2 and sessions are configured like this:: 96 97 config = {} 98 config['webapp2_extras.i18n'] = { 99 'default_locale': ..., 100 } 101 config['webapp2_extras.jinja2'] = { 102 'template_path': ..., 103 } 104 config['webapp2_extras.sessions'] = { 105 'secret_key': ..., 106 } 107 app = webapp2.WSGIApplication(..., config=config) 108 109You only need to set the configuration keys that differ from the default 110ones. For convenience, configurable modules have a 'default_config' 111variable just for the purpose of documenting the default values, e.g.: 112 113 http://webapp-improved.appspot.com/api/extras.i18n.html#webapp2_extras.i18n.default_config 114 115Cookies, quoting & unicode 116-------------------------- 117http://groups.google.com/group/webapp2/msg/985092351378c43e 118http://stackoverflow.com/questions/6839922/unicodedecodeerror-is-raised-when-getting-a-cookie-in-google-app-engine 119 120Marketplace integration 121----------------------- 122 123.. code-block:: xml 124 125 <?xml version="1.0" encoding="UTF-8" ?> 126 <ApplicationManifest xmlns="http://schemas.google.com/ApplicationManifest/2009"> 127 <!-- Name and description pulled from message bundles --> 128 <Name>Tipfy</Name> 129 <Description>A simple application for testing the marketplace.</Description> 130 131 <!-- Support info to show in the marketplace & control panel --> 132 <Support> 133 <!-- URL for application setup as an optional redirect during the install --> 134 <Link rel="setup" href="https://app-id.appspot.com/a/${DOMAIN_NAME}/setup" /> 135 136 <!-- URL for application configuration, accessed from the app settings page in the control panel --> 137 <Link rel="manage" href="https://app-id.appspot.com/a/${DOMAIN_NAME}/manage" /> 138 139 <!-- URL explaining how customers get support. --> 140 <Link rel="support" href="https://app-id.appspot.com/a/${DOMAIN_NAME}/support" /> 141 142 <!-- URL that is displayed to admins during the deletion process, to specify policies such as data retention, how to claim accounts, etc. --> 143 <Link rel="deletion-policy" href="https://app-id.appspot.com/a/${DOMAIN_NAME}/deletion-policy" /> 144 </Support> 145 146 <!-- Show this link in Google's universal navigation for all users --> 147 <Extension id="navLink" type="link"> 148 <Name>Tipfy</Name> 149 <Url>https://app-id.appspot.com/a/${DOMAIN_NAME}/</Url> 150 <!-- This app also uses the Calendar API --> 151 <Scope ref="Users"/> 152 <!-- 153 <Scope ref="Groups"/> 154 <Scope ref="Nicknames"/> 155 --> 156 </Extension> 157 158 <!-- Declare our OpenID realm so our app is white listed --> 159 <Extension id="realm" type="openIdRealm"> 160 <Url>https://app-id.appspot.com</Url> 161 </Extension> 162 163 <!-- Special access to APIs --> 164 <Scope id="Users"> 165 <Url>https://apps-apis.google.com/a/feeds/user/#readonly</Url> 166 <Reason>Users can be selected to gain special permissions to access or modify content.</Reason> 167 </Scope> 168 <!-- 169 <Scope id="Groups"> 170 <Url>https://apps-apis.google.com/a/feeds/group/#readonly</Url> 171 <Reason></Reason> 172 </Scope> 173 <Scope id="Nicknames"> 174 <Url>https://apps-apis.google.com/a/feeds/nickname/#readonly</Url> 175 <Reason></Reason> 176 </Scope> 177 --> 178 </ApplicationManifest> 179