| TODO: documentation |
| =================== |
| Miscelaneous notes abotu things to be documented. |
| |
| Unordered list of topics to be documented |
| ----------------------------------------- |
| - routing |
| |
| - common regular expressions examples |
| |
| - sessions |
| |
| - basic usage & configuration |
| - using multiple sessions in the same request |
| - using different backends |
| - using flashes |
| - updating session arguments (max_age etc) |
| - purging db sessions |
| |
| - i18n (increment existing tutorial) |
| |
| - basic usage & configuration |
| - loading locale/timezone automatically for each request |
| - formatting date/time/datetime |
| - formatting currency |
| - using i18n in templates |
| |
| - jinja2 & mako |
| |
| - basic usage & configuration |
| - setting global filters and variables (using config or factory) |
| |
| - auth |
| |
| - basic usage & configuration |
| - setting up 'own auth' |
| - making user available automatically on each request |
| - purging tokens |
| |
| - config |
| |
| - configuration conventions ("namespaced" configuration for webapp2_extras |
| modules) |
| |
| - tricks |
| |
| - configuration in a separate file |
| - routes in a separate file |
| - reduce verbosity when defining routes (R = webapp2.Route) |
| |
| Common errors |
| ------------- |
| - "TypeError: 'unicode' object is not callable": one possible reason is that |
| the ``RequestHandler`` returned a string. If the handler returns anything, it |
| **must** be a :class:`webapp2.Response` object. Or it must not return |
| anything and write to the response instead using ``self.response.write()``. |
| |
| Secret keys |
| ----------- |
| Add a note about how to generate strong session secret keys:: |
| |
| $ openssl genrsa -out ${PWD}/private_rsa_key.pem 2048 |
| |
| Jinja2 factory |
| -------------- |
| To create Jinja2 with custom filters and global variables:: |
| |
| from webapp2_extras import jinja2 |
| |
| def jinja2_factory(app): |
| j = jinja2.Jinja2(app) |
| j.environment.filters.update({ |
| 'my_filter': my_filter, |
| }) |
| j.environment.globals.update({ |
| 'my_global': my_global, |
| }) |
| return j |
| |
| # When you need jinja, get it passing the factory. |
| j = jinja2.get_jinja2(factory=jinja2_factory) |
| |
| Debugging Jinja2 |
| ---------------- |
| http://stackoverflow.com/questions/3086091/debug-jinja2-in-google-app-engine/3694434#3694434 |
| |
| Configuration notes |
| ------------------- |
| Notice that configuration is set primarily in the application. See: |
| |
| http://webapp-improved.appspot.com/guide/app.html#config |
| |
| By convention, modules that are configurable in webapp2 use the module |
| name as key, to avoid name clashes. Their configuration is then set in |
| a nested dict. So, e.g., i18n, jinja2 and sessions are configured like this:: |
| |
| config = {} |
| config['webapp2_extras.i18n'] = { |
| 'default_locale': ..., |
| } |
| config['webapp2_extras.jinja2'] = { |
| 'template_path': ..., |
| } |
| config['webapp2_extras.sessions'] = { |
| 'secret_key': ..., |
| } |
| app = webapp2.WSGIApplication(..., config=config) |
| |
| You only need to set the configuration keys that differ from the default |
| ones. For convenience, configurable modules have a 'default_config' |
| variable just for the purpose of documenting the default values, e.g.: |
| |
| http://webapp-improved.appspot.com/api/extras.i18n.html#webapp2_extras.i18n.default_config |
| |
| Cookies, quoting & unicode |
| -------------------------- |
| http://groups.google.com/group/webapp2/msg/985092351378c43e |
| http://stackoverflow.com/questions/6839922/unicodedecodeerror-is-raised-when-getting-a-cookie-in-google-app-engine |
| |
| Marketplace integration |
| ----------------------- |
| |
| .. code-block:: xml |
| |
| <?xml version="1.0" encoding="UTF-8" ?> |
| <ApplicationManifest xmlns="http://schemas.google.com/ApplicationManifest/2009"> |
| <!-- Name and description pulled from message bundles --> |
| <Name>Tipfy</Name> |
| <Description>A simple application for testing the marketplace.</Description> |
| |
| <!-- Support info to show in the marketplace & control panel --> |
| <Support> |
| <!-- URL for application setup as an optional redirect during the install --> |
| <Link rel="setup" href="https://app-id.appspot.com/a/${DOMAIN_NAME}/setup" /> |
| |
| <!-- URL for application configuration, accessed from the app settings page in the control panel --> |
| <Link rel="manage" href="https://app-id.appspot.com/a/${DOMAIN_NAME}/manage" /> |
| |
| <!-- URL explaining how customers get support. --> |
| <Link rel="support" href="https://app-id.appspot.com/a/${DOMAIN_NAME}/support" /> |
| |
| <!-- URL that is displayed to admins during the deletion process, to specify policies such as data retention, how to claim accounts, etc. --> |
| <Link rel="deletion-policy" href="https://app-id.appspot.com/a/${DOMAIN_NAME}/deletion-policy" /> |
| </Support> |
| |
| <!-- Show this link in Google's universal navigation for all users --> |
| <Extension id="navLink" type="link"> |
| <Name>Tipfy</Name> |
| <Url>https://app-id.appspot.com/a/${DOMAIN_NAME}/</Url> |
| <!-- This app also uses the Calendar API --> |
| <Scope ref="Users"/> |
| <!-- |
| <Scope ref="Groups"/> |
| <Scope ref="Nicknames"/> |
| --> |
| </Extension> |
| |
| <!-- Declare our OpenID realm so our app is white listed --> |
| <Extension id="realm" type="openIdRealm"> |
| <Url>https://app-id.appspot.com</Url> |
| </Extension> |
| |
| <!-- Special access to APIs --> |
| <Scope id="Users"> |
| <Url>https://apps-apis.google.com/a/feeds/user/#readonly</Url> |
| <Reason>Users can be selected to gain special permissions to access or modify content.</Reason> |
| </Scope> |
| <!-- |
| <Scope id="Groups"> |
| <Url>https://apps-apis.google.com/a/feeds/group/#readonly</Url> |
| <Reason></Reason> |
| </Scope> |
| <Scope id="Nicknames"> |
| <Url>https://apps-apis.google.com/a/feeds/nickname/#readonly</Url> |
| <Reason></Reason> |
| </Scope> |
| --> |
| </ApplicationManifest> |