Key to Grogix:
.P is a grammar production, almost always of a previously declared non-terminal .Pmore is a further dereference, for grouped non-terminals .nt is a non-terminal .t is a terminal .Sequence : 'ListItem' A trivial Google App Engine web application enabling the user to create lists with items (This automatically puts everything in a directory gen__) -------------------------------------------------------------------------- .step 1 : 'form' Starting morphology: overall shape .P : 'start' .nt : 'form main file'
--------------------------------------------------------------------------
.nt : 'form other files' .step 2 : 'form: the GAE target morphology' Starting Morphology (position) POSITIONS / PRODUCTIONS / MORPHOLOGY .P : 'form main file' .file : 'ListItem.py'
.t : 'name' <<< # ListItem.py
>>>.t : 'import' <<< import cgi
>>>import os 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 .nt : 'db' .nt : 'pages' .nt : 'handler map' .t : 'main' <<< def main(): run_wsgi_app(application) if __name__ == "__main__": main() .P : 'form other files' .nt : 'homepage template'
--------------------------------------------------------------------------
.nt : 'launch file' .step 3 : 'data and purpose' There is a simple data model that reflects the purpose of the application In our case, two types of data, one forming a List of the others. A List key is then required for the Item members. PRINCIPLES .template : 'db_model' : 'NAME' <<< class NAME(db.Model):
>>>name = db.StringProperty(multiline=True) .template : 'db_model_ref' : 'NAME', 'REF', 'KEY_LABEL' <<< class NAME(db.Model):
>>>KEY_LABEL = db.ReferenceProperty(REF) name = db.StringProperty(multiline=True) (POSITIONS / PRODUCTIONS / MORPHOLOGY) + (PARAMETERS) .P : 'db' .t : db_model('List')
--------------------------------------------------------------------------
.t : db_model_ref ('Item', 'List', 'list_key') .step 4 : 'Functional Centers and the First Bridge' There are functional centers, which reflect the primary actions of the application, and the technology in which the application runs. POSITIONS / PRODUCTIONS / MORPHOLOGY .P : 'pages' .nt : 'home page'
--------------------------------------------------------------------------
.nt : 'creating lists' .nt : 'creating items' .step 5 : 'A page and its renderer' A page consists of handlers and a renderer POSITIONS / PRODUCTIONS / MORPHOLOGY .P : 'home page' .nt : 'render'
--------------------------------------------------------------------------
.nt : 'handler' .step 6 : 'Class and Method Morphology: Pages' One page, the home page, in this case .P : 'home page' .Pmore : 'handler' .t : 'code'
<<< class HomePage(webapp.RequestHandler):
>>>def get(self): template_values = { 'list_form': 0, 'item_form': 0 } self.response.out.write(render(template_values)) .P : 'home page' .Pmore : 'render' .nt : 'title'
--------------------------------------------------------------------------
.nt : 'parameters' .nt : 'body' .step 7 : 'Class and Method Morphology: Feature handlers' Non-page handlers: for the web, has a GET handler, which sets up the feature and a POST handler, which does it. .P : 'creating lists' .nt : 'title'
.nt : 'parameters' .nt : 'get handler' .nt : 'post handler' .P : 'creating items' .nt : 'title'
--------------------------------------------------------------------------
.nt : 'parameters' .nt : 'get handler' .nt : 'post handler' .step 8 : 'Titles: The Class and Method Bridge' The functional centers are expressed in the form of methods and classes. Among these, the Handlers form a distinct group. .template : 'class_title' : 'NAME' <<< class NAME
>>>.template : 'method_title' : 'NAME' <<< def NAME
>>>.P : 'home page' .Pmore : 'render' .Pmore : 'title' .t : method_title ('render')
.P : 'home page' .Pmore : 'handler' .Pmore : 'title' .t : class_title ('HomePage')
.P : 'creating lists' .Pmore : 'title' .t : class_title ('CreateList')
.P : 'creating items' .Pmore : 'title' .t : class_title ('CreateItem')
--------------------------------------------------------------------------
.step 9 : 'Parameters: for Render and Handler Shells' The handler classes, the calls to render, have explicit arguments. This is for all the 'parameter' non-teminals above. .P : 'home page' .Pmore : 'render' .Pmore : 'parameters' .t : 'for populating templates'
<<< (template_values):
>>>.P : 'home page' .Pmore : 'handler' .Pmore : 'parameters' .t : 'handler class'
<<< (webapp.RequestHandler):
>>>.P : 'creating lists' .Pmore : 'parameters' .t : 'handler class'
<<< (webapp.RequestHandler):
>>>.P : 'creating items' .Pmore : 'parameters' .t : 'handler class'
--------------------------------------------------------------------------
<<< (webapp.RequestHandler):
>>>.step 10 : 'Shape of a handler map' .P : 'handler map' .t : 'app instantiation'
--------------------------------------------------------------------------
<<< application = webapp.WSGIApplication([
>>>.nt : 'URL handler list' .t : 'debug flag' <<< ],debug=True)
>>>.step 11 : 'handler list' .P : 'URL handler list' .t : 'pages'
--------------------------------------------------------------------------
<<< ('/', HomePage),
>>>.t : 'forms with keys' <<< ('/item_form/(.*)/', CreateItem),
>>>.t : 'forms without keys' <<< ('/list_form/', CreateList),
>>>.t : 'posts' <<< ('/create_list/', CreateList),
>>>('/create_item/', CreateItem) .step 12 : 'template valve' .P : 'render' .Pmore : 'body' .t : 'name and parameters'
--------------------------------------------------------------------------
<<< def render (template_values):
>>>.nt : 'template payload' .t : 'get template file' <<< path = os.path.join(os.path.dirname(__file__), 'index.html')
>>>.t : 'return popluated template' <<< return(template.render(path, template_values))
>>>.step 13 : 'Form Get Methods' .P : 'creating lists' .Pmore : 'get handler' .t : 'call with self'
<<< def get (self):
>>>.t : 'template dictionary' <<< template_values = {
>>>'list_form': 1 } .t : 'http response with render' <<< self.response.out.write (render(template_values))
>>>.P : 'creating items' .Pmore : 'get handler' .t : 'call with self and key'
--------------------------------------------------------------------------
<<< def get (self, list_key):
>>>.t : 'template dictionary' <<< template_values = {
>>>'item_form': 1, 'list_key': list_key } .t : 'http response with render' <<< self.response.out.write (render(template_values))
>>>.step 14 : 'Template outline' .P : 'homepage template' .file : 'index.html'
--------------------------------------------------------------------------
.t : 'html top' <<< <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
>>>"http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Passing Keys</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" > </head> <body> <a href="/"><font size="+3"><b>Passing Keys</b></font></a><br> <br><br> .nt: 'list form' .t : 'list iteration' <<< {% for list in lists %}
>>><font size="+3"><b>{{ list.name }}</b></font><br> {% for item in list.items %} <b>*</b> {{ item.name }} <br> {% endfor %} .nt : 'item form' .t : 'html tail' <<< {% endfor %}
>>></body> </html> .step 15 : 'List Form Pathway' .P : 'homepage template' .Pmore : 'list form' .t : 'condition and html'
--------------------------------------------------------------------------
<<< {% if list_form %}
>>><form action="/create_list/" method="post"> <textarea style="background:#eeee00" name="name" rows=1 cols=33></textarea><br> <span align="left"><input type="Submit" name="button" value="Create list"></span> <span style="padding-left:138px"><a href="/">cancel</a></span><br> </form> {% else %} <br> <a href="/list_form/">Create a List</a><br><br> {% endif %} .step 16 : 'Item Form Pathway' .P : 'homepage template' .Pmore : 'item form' .t : 'if form and this item'
--------------------------------------------------------------------------
<<< {% if item_form %}
>>>{% ifequal list.key list_key %} <a name="form"></a> <form action="/create_item/" method="post"> <span style="padding-left:15px"> <textarea style="background:#eeee00" name="name" rows=1 cols=33></textarea><br> </span> <span style="padding-left:15px"> <input type="Submit" name="button" value="Create an item"> </span> <span style="padding-left:130px"> <a href="/">cancel</a> </span> <br> <input type="hidden" name="list_key" value="{{ list_key }}"> </form> {% else %} <br> <span style="padding-left:15px"> <a href="/item_form/{{ list.key }}/#form"> Create an item </a> </span> <br><br> {% endifequal %} {% else %} <br> <span style="padding-left:15px"> <a href="/item_form/{{ list.key }}/#form">Create an item</a> </span> <br><br> {% endif %} .step 17 : 'Pathway posts' .P : 'creating lists' .Pmore: 'post handler' .t : 'cl code'
<<< def post(self):
>>>list = List() list.name = self.request.get('name') list.put() self.redirect("/") .P : 'creating items' .Pmore : 'post handler' .t : 'ci code'
--------------------------------------------------------------------------
<<< def post(self):
>>>item = Item() list_key = self.request.get('list_key') item.list_key = List.get(list_key) item.name = self.request.get('name') item.put() self.redirect("/") .step 18 : 'Template Payload' .P : 'template payload' .t : 'code'
--------------------------------------------------------------------------
<<< lists = db.GqlQuery("SELECT * FROM List")
>>>new_lists = [] for list in lists: items = db.GqlQuery("SELECT * FROM Item Where list_key = :1", list.key()) new_list = { 'name': list.name, 'key': str(list.key()), 'items': items } new_lists.append(new_list) template_values['lists'] = new_lists .step 19 : 'Launch file' .P : 'launch file' .file : 'app.yaml'
.t : 'app.yaml' <<< application: listitem
>>>version: 1 runtime: python api_version: 1 handlers: - url: /(.*).txt static_files: \1.txt upload: (.*).txt - url: /.* script: ListItem.py |