1 TODO: documentation 2 =================== 3 Miscelaneous notes abotu things to be documented. 4 5 Unordered 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 51 Common 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 58 Secret keys 59 ----------- 60 Add a note about how to generate strong session secret keys:: 61 62 $ openssl genrsa -out ${PWD}/private_rsa_key.pem 2048 63 64 Jinja2 factory 65 -------------- 66 To 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 83 Debugging Jinja2 84 ---------------- 85 http://stackoverflow.com/questions/3086091/debug-jinja2-in-google-app-engine/3694434#3694434 86 87 Configuration notes 88 ------------------- 89 Notice that configuration is set primarily in the application. See: 90 91 http://webapp-improved.appspot.com/guide/app.html#config 92 93 By convention, modules that are configurable in webapp2 use the module 94 name as key, to avoid name clashes. Their configuration is then set in 95 a 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 109 You only need to set the configuration keys that differ from the default 110 ones. For convenience, configurable modules have a 'default_config' 111 variable 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 115 Cookies, quoting & unicode 116 -------------------------- 117 http://groups.google.com/group/webapp2/msg/985092351378c43e 118 http://stackoverflow.com/questions/6839922/unicodedecodeerror-is-raised-when-getting-a-cookie-in-google-app-engine 119 120 Marketplace 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