Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

New serve implementation for py 2.7 and django 1.3. Mostly working, t…

…hough profilelinks include needs to be taken out of old profiles
  • Loading branch information...
commit e8f44b26f9eb4ca685185bbba364ed2085ae982f 1 parent 00810eb
@ebidel ebidel authored
View
51 app.yaml
@@ -1,9 +1,17 @@
application: html5rocks-hrd
version: master
-runtime: python
+runtime: python27
+threadsafe: yes
api_version: 1
-default_expiration: "30d"
+env_variables:
+ DJANGO_SETTINGS_MODULE: 'settings'
+
+libraries:
+- name: webapp2
+ version: "latest"
+- name: django
+ version: "latest" #version: "1.3"
inbound_services:
- warmup
@@ -16,6 +24,8 @@ pagespeed:
- ImageAddDimensions
- RemoveComments
+default_expiration: "30d"
+
handlers:
- url: /google75906d613a2a09ba.html
@@ -174,20 +184,33 @@ handlers:
static_files: static/robots.txt
upload: static/robots.txt
-- url: /database/live
- script: main.py
- login: required
+# - url: /database/live
+# script: main.py
+# login: required
-- url: /database/.*
- script: main.py
- login: admin
+# - url: /database/.*
+# script: main.py
+# login: admin
-- url: /admin/.*
- script: $PYTHON_LIB/google/appengine/ext/admin
- login: admin
+# - url: /admin/.*
+# script: $PYTHON_LIB/google/appengine/ext/admin
+# login: admin
-- url: /echoserver
- script: echo.py
+# - url: /echoserver
+# script: echo.py
- url: .*
- script: main.py
+ script: main.app
+
+
+skip_files:
+- ^(.*/)?app\.yaml
+- ^(.*/)?app\.yml
+- ^(.*/)?index\.yaml
+- ^(.*/)?index\.yml
+- ^(.*/)?.*~
+- ^(.*/)?.*\.py[co]
+- ^(.*/)?.*/RCS/.*
+- ^(.*/)?\..*
+- ^(.*/)?.*\.scss$
+- ^(.*/)?.*\.psd$
View
16 common.py
@@ -1,16 +0,0 @@
-import os
-
-if 'SERVER_SOFTWARE' in os.environ:
- PROD = not os.environ['SERVER_SOFTWARE'].startswith('Development')
-else:
- PROD = True
-
-APP_VERSION = os.environ['CURRENT_VERSION_ID'].split('.')[0]
-
-MEMCACHE_KEY_PREFIX = 'newscheme' #APP_VERSION
-MAX_FETCH_LIMIT = 1000
-
-# Users whitelisted to access certain sections the site.
-WHITELISTED_USERS = [
- 'chrome.devrel@gmail.com'
-]
View
1  content/mobile/responsivedesign/en/index.html
@@ -1,4 +1,5 @@
{% extends "tutorial.html" %}
+{% load mixin from templatefilters %}
{% block pagebreadcrumb %}Creating a Mobile-First Responsive Web Design{% endblock %}
View
16 content/tutorials/filters/understanding-css/en/index.html
@@ -1,4 +1,5 @@
{% extends "tutorial.html" %}
+{% load mixin from templatefilters %}
{% block head %}
<style>
@@ -23,8 +24,9 @@
{% block content %}
{% include "warning.html" %}
- <div><figure><img src="images/lens.jpg"></figure></div>
- <h2 id="toc-introduction">Introduction</h2>
+<figure><img src="images/lens.jpg"></figure>
+
+<h2 id="toc-introduction">Introduction</h2>
<p>Filters are a powerful tool that web authors can use to achieve interesting visual effects. In this article we’ll cover the history of filter effects, what they do and how to use them. We’ll cover examples of all the predefined filters defined for CSS with some examples. We’ll also cover performance considerations for using them on desktop and mobile devices since knowing the speed impact of filters is important for a good user experience. Finally we’ll review the current state of implementation in modern browsers.
</p>
<h2 id="toc-history">The past, present and future of filter effects</h2>
@@ -43,10 +45,10 @@ <h2 id="toc-how">How filters work</h2>
So what does a filter do exactly? The easiest way to think of a filter is as a post processing step that does something magical after all your page content has been laid out and drawn.
</p>
<p>
-When a browser loads a web page it needs to apply styles, perform layout and then render the page so there’s something to look at. Filters kick in after all those steps and just before the page is copied to the screen. What they do is take a snapshot of the rendered page as a bitmap image, then perform some graphics magic on the pixels in the snapshot and then draw the result over the top of the original page image. One way to think of them is like a filter placed on the front of a camera lens. What you’re seeing through the lens is the outside world modified by the effect of the filter.
+When a browser loads a web page it needs to apply styles, perform layout and then render the page so there's something to look at. Filters kick in after all those steps and just before the page is copied to the screen. What they do is take a snapshot of the rendered page as a bitmap image, then perform some graphics magic on the pixels in the snapshot and then draw the result over the top of the original page image. One way to think of them is like a filter placed on the front of a camera lens. What you’re seeing through the lens is the outside world modified by the effect of the filter.
</p>
<p>
-This of course means that theres time consumed when drawing a page with filters on it, but using them properly will have minimal impact on the speed of your site.
+This of course means that there's time consumed when drawing a page with filters on it, but using them properly will have minimal impact on the speed of your site.
</p>
<p>
Also, just as you can stack a number of filters in front of each other on your camera lens, you can apply an arbitrary number of filters one after the other to achieve all sorts of effects.
@@ -68,7 +70,7 @@ <h2 id="toc-howto">How to apply a CSS filter</h2>
Using filters from CSS is done by using the ‘filter’ property applied to any visible element on your web page. For a very simple example you could write something like
</p>
<pre class="prettyprint">
- <code>div { {% mixin filter: grayscale(100%); %} }</code>
+<code>div { {% mixin filter: grayscale(100%); %} }</code>
</pre>
<p>
and that would make the content inside all &lt;div&gt; elements on the page turn gray. Great for making your page look like a TV image from the 1940s.
@@ -87,7 +89,7 @@ <h2 id="toc-howto">How to apply a CSS filter</h2>
Most filters take some form of parameter to control how much filtering is done. So for example if you wanted to style your content to be half way between the original color and a grayscale version you’d do it like this:
</p>
<pre class="prettyprint">
- <code>div { {% mixin filter: grayscale(50%); %} }</code>
+<code>div { {% mixin filter: grayscale(50%); %} }</code>
</pre>
<p>
<figure>
@@ -98,7 +100,7 @@ <h2 id="toc-howto">How to apply a CSS filter</h2>
If you want to apply a number of different filters one after another, it’s easy - just place them in order in your CSS like so:
</p>
<pre class="prettyprint">
- <code>div { {% mixin filter: grayscale(100%) sepia(100%); %} }</code>
+<code>div { {% mixin filter: grayscale(100%) sepia(100%); %} }</code>
</pre>
<p>
That example will first make all the original color grayscale and then apply a sepia effect, and would end up looking like:</p>
View
1  content/tutorials/getusermedia/intro/en/header.html
@@ -1,4 +1,5 @@
{% extends "tutorial.html" %}
+{% load mixin from templatefilters %}
{% block pagebreadcrumb %}{{ tut.title }}{% endblock %}
View
1  content/tutorials/getusermedia/intro/en/index.html
@@ -1,4 +1,5 @@
{% extends "tutorial.html" %}
+{% load mixin from templatefilters %}
{% block pagebreadcrumb %}{{ tut.title }}{% endblock %}
View
11 content/tutorials/indexeddb/uidatabinding/en/index.html
@@ -1,4 +1,5 @@
{% extends "tutorial.html" %}
+{% load verbatim from templatefilters %}
{% block html5badge %}
<img src="/static/images/identity/html5-badge-h-storage.png" width="133" height="64" alt="This article is powered by HTML5 Offline & Storage" title="This article is powered by HTML5 Offline & Storage" />
@@ -40,7 +41,7 @@ <h2 id="toc-gettingstarted">Getting Started</h2>
&lt;div id="displayEmployee">&lt;/div>
</pre>
-<p>Not a lot, right? There are three main aspects to this UI that we care about. First is the field, name that will be used for autocomplete. It loads disabled and will be enabled later via JavaScript. The span next to it is used during the initial seed to provide updates to the user. Finally, the div with the id displayEmployee will be used when you select an employee from the autosuggest.
+<p>Not a lot, right? There are three main aspects to this UI that we care about. First is the field, "name" that will be used for autocomplete. It loads disabled and will be enabled later via JavaScript. The span next to it is used during the initial seed to provide updates to the user. Finally, the div with the id displayEmployee will be used when you select an employee from the autosuggest.
<p>Now let's take a look at the JavaScript. There's a lot to digest here so we'll take it step by step. The full code will be available at the end so you can see it in it's entirety.
@@ -63,20 +64,22 @@ <h2 id="toc-gettingstarted">Getting Started</h2>
<pre class="prettyprint">
$(document).ready(function() {
-console.log("Startup...");
+ console.log("Startup...");
+ ...
+});
</pre>
<p>Our demo makes use of <a href="http://handlebarsjs.com/">Handlebars.js</a> to display the employee details. That isn't used till later, but we can go ahead and compile our template now and get it out of the way. We've got a script block set up as a Handlebars-recognized type. It isn't terribly fancy, but does make it easier to display the dynamic HTML.
-<pre class="prettyprint">
{% verbatim %}
+<pre class="prettyprint">
&lt;script id="employeeTemplate" type="text/x-handlerbars-template">
&lt;h2>{{lastname}}, {{firstname}}&lt;/h2>
Department: {{department}}&lt;br/>
Email: &lt;a href='mailto:{{email}}'>{{email}}&lt;/a>
&lt;/script>
-{% endverbatim %}
</pre>
+{% endverbatim %}
<p>This is then compiled back in our JavaScript like so:
View
1  content/tutorials/regions/adobe/en/header.html
@@ -1,4 +1,5 @@
{% extends "tutorial.html" %}
+{% load mixin from templatefilters %}
{% block pagebreadcrumb %}{{ tut.title }}{% endblock %}
View
1  content/tutorials/regions/adobe/en/index.html
@@ -1,4 +1,5 @@
{% extends "tutorial.html" %}
+{% load mixin from templatefilters %}
{% block pagebreadcrumb %}{{ tut.title }}{% endblock %}
View
0  templatetags/__init__.py → customtags/__init__.py
File renamed without changes
View
0  customtags/templatetags/__init__.py
No changes.
View
41 templatetags/templatefilters.py → customtags/templatetags/templatefilters.py
@@ -12,18 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-
-import os
-import logging
import time
-from google.appengine.ext import webapp
-from google.appengine.ext.webapp import template
-import django.template
+from django import template
+
+register = template.Library()
-register = webapp.template.create_template_register()
-class TOCNode(django.template.Node):
+class TOCNode(template.Node):
def render(self, context):
if not context.has_key('toc'):
return ''
@@ -44,16 +40,15 @@ def render(self, context):
return output
+@register.tag(name='toc')
def do_toc(parser, token):
return TOCNode()
-register.tag('toc', do_toc)
-
-class ProfileLink(django.template.Node):
+class ProfileLink(template.Node):
def __init__(self, ids):
self.ids = ids
- self.profiles = [] #common.get_profiles()
+ self.profiles = []
def render(self, context):
names = []
@@ -67,13 +62,12 @@ def render(self, context):
return ',<br> '.join(names)
+@register.tag(name='profilelinks')
def do_profile_links(parser, token):
ids = token.split_contents()
ids.pop(0) # Remove tag name.
return ProfileLink(ids)
-register.tag('profilelinks', do_profile_links)
-
class ProfileLinkSimple(ProfileLink):
def __init__(self, ids):
@@ -91,15 +85,14 @@ def render(self, context):
return ', '.join(names)
+@register.tag(name='simpleprofilelink')
def do_simple_profile_link(parser, token):
ids = token.split_contents()
ids.pop(0) # Remove tag name.
return ProfileLinkSimple(ids)
-register.tag('simpleprofilelink', do_simple_profile_link)
-
-class MixinAnnotation(django.template.Node):
+class MixinAnnotation(template.Node):
def __init__(self, props):
self.prop = props[0]
@@ -131,14 +124,12 @@ def render(self, context):
prefix_list, tooltip_id,
self.prop, self.val))
-
+@register.tag(name='mixin')
def do_mixin_annotation(parser, token):
props = token.split_contents()
props.pop(0) # Remove tag name
return MixinAnnotation(props)
-register.tag('mixin', do_mixin_annotation)
-
"""
jQuery templates use constructs like:
@@ -153,7 +144,7 @@ def do_mixin_annotation(parser, token):
to output the contents with no changes.
"""
-class VerbatimNode(django.template.Node):
+class VerbatimNode(template.Node):
def __init__(self, text):
self.text = text
@@ -169,14 +160,14 @@ def verbatim(parser, token):
token = parser.tokens.pop(0)
if token.contents == 'endverbatim':
break
- if token.token_type == django.template.TOKEN_VAR:
+ if token.token_type == template.TOKEN_VAR:
text.append('{{')
- elif token.token_type == django.template.TOKEN_BLOCK:
+ elif token.token_type == template.TOKEN_BLOCK:
text.append('{%')
text.append(token.contents)
- if token.token_type == django.template.TOKEN_VAR:
+ if token.token_type == template.TOKEN_VAR:
text.append('}}')
- elif token.token_type == django.template.TOKEN_BLOCK:
+ elif token.token_type == template.TOKEN_BLOCK:
text.append('%}')
return VerbatimNode(''.join(text))
View
0  templatetags/verbatim.py → customtags/templatetags/verbatim.py
File renamed without changes
View
22 django_settings.py
@@ -1,22 +0,0 @@
-import os
-
-DEBUG = False
-TEMPLATE_DEBUG = DEBUG
-
-# Hack to get templates to render in django 1.2.
-INSTALLED_APPS = (
- 'nothing',
-)
-
-ROOT_DIR = os.path.abspath(os.path.dirname(__file__))
-
-TEMPLATE_DIRS = (
- os.path.join(ROOT_DIR, 'templates'),
-)
-
-# i18n Configuration
-LANGUAGE_CODE = 'en'
-USE_I18N = True
-LOCALE_PATHS = (
- os.path.join(ROOT_DIR, 'conf', 'locale'),
-)
View
121 main.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010 Google Inc.
+# Copyright 2012 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License")
# you may not use this file except in compliance with the License.
@@ -14,8 +14,7 @@
# limitations under the License.
#
-__author__ = ('kurrik@html5rocks.com (Arne Kurrik) ',
- 'ericbidelman@html5rocks.com (Eric Bidelman)')
+__author__ = 'ericbidelman@html5rocks.com (Eric Bidelman)'
# Standard Imports
import datetime
@@ -24,15 +23,10 @@
import os
import re
import urllib2
+import webapp2
import yaml
-# Use Django 1.2.
-from google.appengine.dist import use_library
-use_library('django', '1.2')
-
-os.environ['DJANGO_SETTINGS_MODULE'] = 'django_settings'
-
-import common
+import settings
import models
# Libraries
@@ -52,16 +46,28 @@
from google.appengine.api import memcache
from google.appengine.api import users
from google.appengine.ext import db
-from google.appengine.ext import webapp
-from google.appengine.ext.webapp import template
-from google.appengine.ext.webapp.util import run_wsgi_app
+#from google.appengine.ext import webapp
+#from google.appengine.ext.webapp import template
+#from google.appengine.ext.webapp.util import run_wsgi_app
+
+from django.template.loader import render_to_string
+
+#template.register_template_library('templatetags.templatefilters')
+
+
+# class LoggingHandler(webapp2.RequestHandler):
+
+# def __init__(self, request, response):
+# self.initialize(request, response)
-template.register_template_library('templatetags.templatefilters')
+# # Settings can't be global in python 2.7 env.
+# logging.getLogger().setLevel(logging.DEBUG)
+# os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
-BASEDIR = os.path.dirname(__file__)
-class ContentHandler(webapp.RequestHandler):
+class ContentHandler(webapp2.RequestHandler):
+ BASEDIR = os.path.dirname(__file__)
FEED_RESULTS_LIMIT = 20
FEATURE_PAGE_WHATS_NEW_LIMIT = 10
@@ -82,12 +88,14 @@ def is_awesome_mobile_device(self):
return browser.find('Android') != -1 or browser.find('iPhone') != -1
def get_toc(self, path):
- if not (re.search('', path) or re.search('/mobile/', path)):
+ # Only have TOC on tutorial pages.
+ if not (re.search('/tutorials', path) or re.search('/mobile', path)):
return ''
- toc = memcache.get('%s|toc|%s' % (common.MEMCACHE_KEY_PREFIX, path))
+ toc = memcache.get('%s|toc|%s' % (settings.MEMCACHE_KEY_PREFIX, path))
if toc is None or not self.request.cache:
- template_text = template.render(path, {})
+ template_text = render_to_string(path, {})
+
parser = html5lib.HTMLParser(tree=treebuilders.getTreeBuilder("dom"))
dom_tree = parser.parse(template_text)
walker = treewalkers.getTreeWalker("dom")
@@ -108,12 +116,12 @@ def get_toc(self, path):
elif element['type'] == 'EndTag' and current is not None:
toc.append(current)
current = None
- memcache.set('%s|toc|%s' % (common.MEMCACHE_KEY_PREFIX, path), toc, 3600)
+ memcache.set('%s|toc|%s' % (settings.MEMCACHE_KEY_PREFIX, path), toc, 3600)
return toc
def get_feed(self, path):
- articles = memcache.get('%s|feed|%s' % (common.MEMCACHE_KEY_PREFIX, path))
+ articles = memcache.get('%s|feed|%s' % (settings.MEMCACHE_KEY_PREFIX, path))
if articles is None or not self.request.cache:
# DB query is memcached in get_all(). Limit to last several results
tutorials = models.Resource.get_all(order='-publication_date',
@@ -139,7 +147,7 @@ def get_feed(self, path):
# Cache feed for 24hrs.
memcache.set(
- '%s|feed|%s' % (common.MEMCACHE_KEY_PREFIX, path), articles, 86400)
+ '%s|feed|%s' % (settings.MEMCACHE_KEY_PREFIX, path), articles, 86400)
return articles
@@ -172,6 +180,9 @@ def render(self, data={}, template_path=None, status=None,
pagename = re.sub('/$|-$', '', pagename)
pagename = re.sub('^-', '', pagename)
+
+ logging.info(template_path)
+
# Add template data to every request.
template_data = {
'toc': self.get_toc(template_path),
@@ -180,7 +191,7 @@ def render(self, data={}, template_path=None, status=None,
'host': '%s://%s' % (self.request.scheme, self.request.host),
'is_mobile': self.is_awesome_mobile_device(),
'current': current,
- 'prod': common.PROD
+ 'prod': settings.PROD
}
# If the tutorial contains a social URL override, use it.
@@ -211,7 +222,8 @@ def render(self, data={}, template_path=None, status=None,
# Add CORS support entire site.
self.response.headers.add_header('Access-Control-Allow-Origin', '*')
self.response.headers.add_header('X-UA-Compatible', 'IE=Edge,chrome=1')
- self.response.out.write(template.render(template_path, template_data))
+ #self.response.out.write(template.render(template_path, template_data))
+ self.response.out.write(render_to_string(template_path, template_data))
def render_atom_feed(self, template_path, data):
prefix = '%s://%s' % (self.request.scheme, self.request.host)
@@ -309,9 +321,9 @@ def get(self, relpath):
if ((relpath == '' or relpath[-1] == '/') or # Landing page.
(relpath[-1] != '/' and relpath in ['mobile', 'tutorials', 'features',
'gaming', 'business'])):
- path = os.path.join(BASEDIR, 'content', relpath, 'index.html')
+ path = os.path.join(self.BASEDIR, 'content', relpath, 'index.html')
else:
- path = os.path.join(BASEDIR, 'content', relpath)
+ path = os.path.join(self.BASEDIR, 'content', relpath)
# Render the .html page if it exists. Otherwise, check that the Atom feed
# the user is requesting has a corresponding .html page that exists.
@@ -425,7 +437,7 @@ def get(self, relpath):
if r.url.startswith('/'):
# Localize title and description if article is localized.
- filepath = os.path.join(BASEDIR, 'content', r.url[1:], self.locale,
+ filepath = os.path.join(self.BASEDIR, 'content', r.url[1:], self.locale,
'index.html')
if os.path.isfile(filepath):
if r.title:
@@ -466,7 +478,7 @@ def get(self, relpath):
for r in updates:
if r.url.startswith('/'):
# Localize title if article is localized.
- filepath = os.path.join(BASEDIR, 'content', r.url[1:], self.locale,
+ filepath = os.path.join(self.BASEDIR, 'content', r.url[1:], self.locale,
'index.html')
if r.url.startswith('/') and os.path.isfile(filepath) and r.title:
r.title = _(r.title)
@@ -487,7 +499,7 @@ def get(self, relpath):
else:
self.render(status=404, message='Page Not Found',
- template_path=os.path.join(BASEDIR, 'templates/404.html'))
+ template_path=os.path.join(self.BASEDIR, 'templates/404.html'))
def handle_exception(self, exception, debug_mode):
if debug_mode:
@@ -495,7 +507,7 @@ def handle_exception(self, exception, debug_mode):
else:
# Display a generic 500 error page.
self.render(status=500, message='Server Error',
- template_path=os.path.join(BASEDIR, 'templates/500.html'))
+ template_path=os.path.join(self.BASEDIR, 'templates/500.html'))
class DBHandler(ContentHandler):
@@ -591,7 +603,7 @@ def get(self, relpath, post_id=None):
# Restrict access to this page to admins and whitelisted users.
if (not users.is_current_user_admin() and
- user.email() not in common.WHITELISTED_USERS):
+ user.email() not in settings.WHITELISTED_USERS):
return self.redirect('/')
entity = models.LiveData.all().get()
@@ -622,32 +634,32 @@ def get(self, relpath, post_id=None):
relpath=relpath)
elif (relpath == 'drop_all'):
- if common.PROD:
+ if settings.PROD:
return self.response.out.write('Handler not allowed in production.')
self._NukeDB()
elif (relpath == 'load_tutorials'):
- if common.PROD:
+ if settings.PROD:
return self.response.out.write('Handler not allowed in production.')
self._AddTestResources()
elif (relpath == 'load_authors'):
- if common.PROD:
+ if settings.PROD:
return self.response.out.write('Handler not allowed in production.')
self._AddTestAuthors()
elif (relpath == 'load_playground_samples'):
- if common.PROD:
+ if settings.PROD:
return self.response.out.write('Handler not allowed in production.')
self._AddTestPlaygroundSamples()
elif (relpath == 'load_studio_samples'):
- if common.PROD:
+ if settings.PROD:
return self.response.out.write('Handler not allowed in production.')
self._AddTestStudioSamples()
elif (relpath == 'load_all'):
- if common.PROD:
+ if settings.PROD:
return self.response.out.write('Handler not allowed in production.')
# TODO(ericbidelman): Make this async.
@@ -683,7 +695,7 @@ def get(self, relpath, post_id=None):
'tutorial_form': tutorial_form,
# get_all() not used b/c we don't care about caching on this page.
'resources': (models.Resource.all().order('-publication_date')
- .fetch(limit=common.MAX_FETCH_LIMIT)),
+ .fetch(limit=settings.MAX_FETCH_LIMIT)),
'post_id': post_id and int(post_id) or ''
}
return self.render(data=template_data,
@@ -903,15 +915,26 @@ def get_as_db(self, tag, order=None, limit=None):
return self._get(tag, order=order, limit=limit)
-def main():
- application = webapp.WSGIApplication([
- ('/api/(.*)', APIHandler),
- ('/database/(.*)/(.*)', DBHandler),
- ('/database/(.*)', DBHandler),
- ('/tags/(.*)/(.*)', TagsHandler),
- ('/(.*)', ContentHandler)
- ], debug=not common.PROD)
- run_wsgi_app(application)
+def handle_404(request, response, exception):
+ response.write('Oops! Not Found.')
+ response.set_status(404)
+
+def handle_500(request, response, exception):
+ logging.exception(exception)
+ response.write('Oops! Internal Server Error.')
+ response.set_status(500)
+
+
+# App URL routes.
+routes = [
+ ('/api/(.*)', APIHandler),
+ ('/database/(.*)/(.*)', DBHandler),
+ ('/database/(.*)', DBHandler),
+ ('/tags/(.*)/(.*)', TagsHandler),
+ ('/(.*)', ContentHandler)
+]
-if __name__ == '__main__':
- main()
+app = webapp2.WSGIApplication(routes, debug=settings.DEBUG)
+app.error_handlers[404] = handle_404
+if settings.PROD and settings.DEBUG:
+ app.error_handlers[500] = handle_500
View
16 models.py
@@ -3,20 +3,20 @@
from google.appengine.ext.db import djangoforms
from django import forms
-import common
+import settings
def get_profiles(update_cache=False):
- profiles = memcache.get('%s|profiles' % (common.MEMCACHE_KEY_PREFIX))
+ profiles = memcache.get('%s|profiles' % (settings.MEMCACHE_KEY_PREFIX))
if profiles is None or update_cache:
profiles = {}
- authors = Author.all().fetch(limit=common.MAX_FETCH_LIMIT)
+ authors = Author.all().fetch(limit=settings.MAX_FETCH_LIMIT)
for author in authors:
author_id = author.key().name()
profiles[author_id] = author.to_dict()
profiles[author_id]['id'] = author_id
- memcache.set('%s|profiles' % (common.MEMCACHE_KEY_PREFIX), profiles)
+ memcache.set('%s|profiles' % (settings.MEMCACHE_KEY_PREFIX), profiles)
return profiles
@@ -81,9 +81,9 @@ class Resource(DictModel):
@classmethod
def get_all(self, order=None, limit=None, qfilter=None):
- limit = limit or common.MAX_FETCH_LIMIT
+ limit = limit or settings.MAX_FETCH_LIMIT
- key = '%s|tutorials' % (common.MEMCACHE_KEY_PREFIX,)
+ key = '%s|tutorials' % (settings.MEMCACHE_KEY_PREFIX,)
if order is not None:
key += '|%s' % (order,)
@@ -108,7 +108,7 @@ def get_all(self, order=None, limit=None, qfilter=None):
@classmethod
def get_tutorials_by_author(self, author_id):
tutorials_by_author = memcache.get(
- '%s|tutorials_by|%s' % (common.MEMCACHE_KEY_PREFIX, author_id))
+ '%s|tutorials_by|%s' % (settings.MEMCACHE_KEY_PREFIX, author_id))
if tutorials_by_author is None:
tutorials_by_author1 = Author.get_by_key_name(author_id).author_one_set
tutorials_by_author2 = Author.get_by_key_name(author_id).author_two_set
@@ -121,7 +121,7 @@ def get_tutorials_by_author(self, author_id):
tutorials_by_author.sort(key=lambda x: x.publication_date, reverse=True)
memcache.set(
- '%s|tutorials_by|%s' % (common.MEMCACHE_KEY_PREFIX, author_id),
+ '%s|tutorials_by|%s' % (settings.MEMCACHE_KEY_PREFIX, author_id),
tutorials_by_author)
return tutorials_by_author
View
42 settings.py
@@ -0,0 +1,42 @@
+import os
+
+# Hack to get custom tags working django 1.3 + python27.
+INSTALLED_APPS = (
+ 'nothing',
+ 'customtags',
+)
+
+ROOT_DIR = os.path.abspath(os.path.dirname(__file__))
+
+TEMPLATE_DIRS = (
+ os.path.join(ROOT_DIR, ''), # templates can be anywhere in root dir.
+ os.path.join(ROOT_DIR, 'content'),
+ os.path.join(ROOT_DIR, 'content', 'features'),
+)
+
+# i18n Configuration
+LANGUAGE_CODE = 'en'
+USE_I18N = True
+LOCALE_PATHS = (
+ os.path.join(ROOT_DIR, 'conf', 'locale'),
+)
+
+if (os.getenv('SERVER_SOFTWARE', '').startswith('Google App Engine') or
+ os.getenv('SETTINGS_MODE') == 'prod'):
+ PROD = True
+else:
+ PROD = False
+
+DEBUG = not PROD
+TEMPLATE_DEBUG = DEBUG
+
+# App settings #################################################################
+APP_VERSION = os.environ['CURRENT_VERSION_ID'].split('.')[0]
+
+MEMCACHE_KEY_PREFIX = 'newscheme' #APP_VERSION
+MAX_FETCH_LIMIT = 1000
+
+# Users whitelisted to access certain sections the site.
+WHITELISTED_USERS = [
+ 'chrome.devrel@gmail.com'
+]
View
1  templates/base.html
@@ -178,7 +178,6 @@ <h1 id="title">
</ul>
</nav>
-
<nav class="paginator features">
<ul class="offline">
<li><a class="next" href="/{{LANGUAGE_CODE}}/features/storage">{% trans "Storage" %}</a></li>
View
2  templates/tutorial.html
@@ -1,5 +1,7 @@
{% extends "base.html" %}
{% load i18n %}
+{% load toc from templatefilters %}
+
{% get_current_language as LANGUAGE_CODE %}
{% block headauthor %}{{ tut.author.given_name }} {{ tut.author.family_name }} - {{ tut.author.email }}{% endblock %}
Please sign in to comment.
Something went wrong with that request. Please try again.