SlideShare a Scribd company logo
1 of 20
Download to read offline
Practical Google App Engine
   Applications in Python

        上官林傑 (ericsk)
         COSCUP 2009



              http://tinyurl.com/coscup-appengine
Outline

 Effective Datastore API
 Data Manipulation Efficiency
 Effective Memcache
 Zip Import & Zip Serve
 Conclusion
Quota Limit on App Engine




      from: http://www.flickr.com/photos/kevin814/3587610731/
What's Datastore

 Datastore is a kind of key-value database built on GFS.
    scalable
    Kind-based data entities. (not table-based)
    add/remove properties dynamically




    Relational DB Table




                                             Datastore
Avoid Heavily-Indexing

 Datastore will create index on each property.
    If there're many properties in your data, indexing will
    downgrade performance.
    If a property is not used for filtering nor ordering, add
    indexed=False to the data model declaration.

    class Foo(db.Model):
        name = db.StringProperty(required=True)
        bar = db.StringProperty(indexed=False)
Minimize Datastore API Calls

 CRUD data entities by keys:
   Ineffective Way:
    keys = [key1, key2, key3, ..., keyN]
    products = []
    for key in keys:
        products.append(db.get(key))
    ...
    Effective Way:
    keys = [key1, key2, key3, ..., keyN]
    products = db.get(keys)
    Same as db.put(), db.delete().
Re-bind GqlQuery Object

 Use prepared GqlQuery data:
    Ineffective way:
    conds = [['abc', 'def'], ['123', '456'], ...]
    for cond in conds:
        query = db.GqlQuery('SELECT * FROM Foo WHERE first = :
    first, second = :second', first=cond[0], second=cond[1])
        ....
    Effective way:
    conds = [['abc', 'def'], ['123', '456'], ...]
    prepared_query = db.GqlQuery('SELECT * FROM Foo WHERE first
    = :first, second = :second')
    for cond in conds:
         query = prepared_query.bind(first=cond[0], second=cond
    [1])
         ....
Avoid Disjunctions

 IN or != operator generates more queries.
    SELECT * FROM Foo WHERE a IN ('x', 'y') and b != 3
    splits into 4 queries
        SELECT   *   FROM   Foo   WHERE   a   == 'x'
        SELECT   *   FROM   Foo   WHERE   a   == 'y'
        SELECT   *   FROM   Foo   WHERE   b   < 3
        SELECT   *   FROM   Foo   WHERE   b   > 3
 Fetches all data and filters them manually.
How to Fetch More Than 1000 Results

 Datastore API fetches no more than 1000 results once a call
 Fetches more than 1000 results (SLOW, may cause TLE)

 data = Foo.gql('ORDER BY __key__').fetch(1000)
 last_key = data[-1].key()
 results = data

 while len(data) == 1000:
     data = Foo.gql('WHERE __key__ > :1 ORDER BY __key__',
 last_key).fetch(1000)
     last_key = data[-1].key()
     results.extend(data)
Put Data into Entity Group
Put Data into Entity Group (cont.)

  Put data into an entity group:
  forum = Forum.get_by_key_name('HotForum')
  topic = Topic(key_name='Topic1',......, parent=forum).put()
  Load data from an entity group:
  topic = Topic.get_by_key_name('Topic1',
      parent=db.Key.from_path('Forum', 'HotForum'))
Sharding Data

 Write data in parallel
    avoiding write contention
 Sharding data with key_name:
 class Counter(db.Model):
     name = db.StringProperty()
     count = db.IntegerProperty()
 ...
 def incr_counter(counter_name):
     shard = random.randint(0, NUM_SHARDS - 1)
     counter = Counter.get_or_insert(shard, name=counter_name)
     counter.count += 1
     counter.put()
Effective Caching

 Caching page content
    Without caching
    ....
    self.response.out.write(
         template.render('index.html', {})
    )
    ...
    With Caching
    page_content = memcache.get('index_page_content')
    if page_content is None:
         page_content = template.render('index.html',{})
    self.response.out.write(page_content)
Effective Caching (cont.)

  Caching frequently fetched entities
     Without caching
     ....
     products = Product.gql('WHERE price < 100').fetch(1000)
     from django.utils import simplejson
     self.response.out.write(simplejson.dumps(products))
     With caching
     ...
     products = memcache.get('products_lt_100')
     if products is None:
         products = Product.gql('WHERE price < 100').fetch(1000)
     from django.utils import simplejson
     self.response.out.write(simplejson.dumps(products))
Zipimport & ZipServe

 ZipImport:
 Zip your library and then import modules within it.
 ZipServe:
 Zip your static/asset files, then serve them with zipserve.
 WHY?
 You can ONLY put 1000 files in your application.
Zipimport

 For example, you want to use Google Data client library in
 your application.
    You have to put gdata/ and atom/ packages into your
    application directory.
    With zipimport, you can zip them:
    application/
        app.yaml
        ....
        atom.zip
        gdata.zip
        ....
Zipimport (cont.)

    import gdata modules in your script:
    ...
    import sys

    sys.path.append('atom.zip')
    sys.path.append('gdata.zip')
    ....
    from gdata.doc import service
Zipserve

 For example, you want to use TinyMCE library
    You have to put TinyMCE library into your directory. However, it
    contains lots of files.
    With zipserve, you can zip the library, and configure the app.
    yaml:
    ...
    - url: /tinymce/.*
      script: $PYTHON_LIB/google/appengine/ext/zipserve

    The filename MUST be the same as the directory name. In this
    sample, the TinyMCE library should be zipped into tinymce.
    zip.
Conclusion - How to Write Better
GAE Apps?
 Read the Articles on Google App Engine site.
 Trace the source from SDK
    Maybe you will find the undocumented API.
 Read http://practicalappengine.blogspot.com/ (in Traditional
 Chinese)
 Develop apps!
台北, Taipei


http://taipei-gtug.org/

More Related Content

What's hot

What's hot (20)

Boost your angular app with web workers
Boost your angular app with web workersBoost your angular app with web workers
Boost your angular app with web workers
 
[Quase] Tudo que você precisa saber sobre tarefas assíncronas
[Quase] Tudo que você precisa saber sobre  tarefas assíncronas[Quase] Tudo que você precisa saber sobre  tarefas assíncronas
[Quase] Tudo que você precisa saber sobre tarefas assíncronas
 
Swift LA Meetup at eHarmony- What's New in Swift 2.0
Swift LA Meetup at eHarmony- What's New in Swift 2.0Swift LA Meetup at eHarmony- What's New in Swift 2.0
Swift LA Meetup at eHarmony- What's New in Swift 2.0
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
 
Angular promises and http
Angular promises and httpAngular promises and http
Angular promises and http
 
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
 
Automation in angular js
Automation in angular jsAutomation in angular js
Automation in angular js
 
Firebase ng2 zurich
Firebase ng2 zurichFirebase ng2 zurich
Firebase ng2 zurich
 
Typescript barcelona
Typescript barcelonaTypescript barcelona
Typescript barcelona
 
And the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportAnd the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack Support
 
Method and decorator
Method and decoratorMethod and decorator
Method and decorator
 
Avoiding callback hell in Node js using promises
Avoiding callback hell in Node js using promisesAvoiding callback hell in Node js using promises
Avoiding callback hell in Node js using promises
 
Présentation de HomeKit
Présentation de HomeKitPrésentation de HomeKit
Présentation de HomeKit
 
Confident Refactoring - Ember SF Meetup
Confident Refactoring - Ember SF MeetupConfident Refactoring - Ember SF Meetup
Confident Refactoring - Ember SF Meetup
 
Callbacks and control flow in Node js
Callbacks and control flow in Node jsCallbacks and control flow in Node js
Callbacks and control flow in Node js
 
Tools for Solving Performance Issues
Tools for Solving Performance IssuesTools for Solving Performance Issues
Tools for Solving Performance Issues
 
Containers & Dependency in Ember.js
Containers & Dependency in Ember.jsContainers & Dependency in Ember.js
Containers & Dependency in Ember.js
 
AngularJS Tips&Tricks
AngularJS Tips&TricksAngularJS Tips&Tricks
AngularJS Tips&Tricks
 
How to Create a l10n Payroll Structure
How to Create a l10n Payroll StructureHow to Create a l10n Payroll Structure
How to Create a l10n Payroll Structure
 
How to build an AngularJS backend-ready app WITHOUT BACKEND
How to build an AngularJS backend-ready app WITHOUT BACKEND How to build an AngularJS backend-ready app WITHOUT BACKEND
How to build an AngularJS backend-ready app WITHOUT BACKEND
 

Viewers also liked (9)

self introduction
self introductionself introduction
self introduction
 
Naples
NaplesNaples
Naples
 
www.Disconshopbd
www.Disconshopbdwww.Disconshopbd
www.Disconshopbd
 
The Google App Engine Oil Framework
The Google App Engine Oil FrameworkThe Google App Engine Oil Framework
The Google App Engine Oil Framework
 
Self Introduction
Self IntroductionSelf Introduction
Self Introduction
 
2005 baltimore-ravens-rex-ryan
2005 baltimore-ravens-rex-ryan2005 baltimore-ravens-rex-ryan
2005 baltimore-ravens-rex-ryan
 
In
InIn
In
 
Nokia Sales presentation 07 & 08 At Ctg
Nokia Sales presentation  07 & 08 At CtgNokia Sales presentation  07 & 08 At Ctg
Nokia Sales presentation 07 & 08 At Ctg
 
Introducing .NET Core Open Source
Introducing .NET Core Open SourceIntroducing .NET Core Open Source
Introducing .NET Core Open Source
 

Similar to Practical Google App Engine Applications In Py

Similar to Practical Google App Engine Applications In Py (20)

Optimization in django orm
Optimization in django ormOptimization in django orm
Optimization in django orm
 
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
 
How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF
 
How te bring common UI patterns to ADF
How te bring common UI patterns to ADFHow te bring common UI patterns to ADF
How te bring common UI patterns to ADF
 
Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)
 
Eclipse Tricks
Eclipse TricksEclipse Tricks
Eclipse Tricks
 
Django
DjangoDjango
Django
 
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
 
Practical Celery
Practical CeleryPractical Celery
Practical Celery
 
Pruebas unitarias con django
Pruebas unitarias con djangoPruebas unitarias con django
Pruebas unitarias con django
 
Django design-patterns
Django design-patternsDjango design-patterns
Django design-patterns
 
Datagrids with Symfony 2, Backbone and Backgrid
Datagrids with Symfony 2, Backbone and BackgridDatagrids with Symfony 2, Backbone and Backgrid
Datagrids with Symfony 2, Backbone and Backgrid
 
Datagrids with Symfony 2, Backbone and Backgrid
Datagrids with Symfony 2, Backbone and BackgridDatagrids with Symfony 2, Backbone and Backgrid
Datagrids with Symfony 2, Backbone and Backgrid
 
Apache Calcite Tutorial - BOSS 21
Apache Calcite Tutorial - BOSS 21Apache Calcite Tutorial - BOSS 21
Apache Calcite Tutorial - BOSS 21
 
Database connectivity in python
Database connectivity in pythonDatabase connectivity in python
Database connectivity in python
 
Automation with Ansible and Containers
Automation with Ansible and ContainersAutomation with Ansible and Containers
Automation with Ansible and Containers
 
Android workshop
Android workshopAndroid workshop
Android workshop
 
Using Task Queues and D3.js to build an analytics product on App Engine
Using Task Queues and D3.js to build an analytics product on App EngineUsing Task Queues and D3.js to build an analytics product on App Engine
Using Task Queues and D3.js to build an analytics product on App Engine
 
Inside PyMongo - MongoNYC
Inside PyMongo - MongoNYCInside PyMongo - MongoNYC
Inside PyMongo - MongoNYC
 
Unsupervised Aspect Based Sentiment Analysis at Scale
Unsupervised Aspect Based Sentiment Analysis at ScaleUnsupervised Aspect Based Sentiment Analysis at Scale
Unsupervised Aspect Based Sentiment Analysis at Scale
 

More from Eric ShangKuan

Internet Explorer 10: 重新想像網站設計
Internet Explorer 10: 重新想像網站設計Internet Explorer 10: 重新想像網站設計
Internet Explorer 10: 重新想像網站設計
Eric ShangKuan
 
透過 Windows Azure Mobile Services 開發各平台 Apps
透過 Windows Azure Mobile Services 開發各平台 Apps透過 Windows Azure Mobile Services 開發各平台 Apps
透過 Windows Azure Mobile Services 開發各平台 Apps
Eric ShangKuan
 
Metro Style Apps from C++ Developers' View
Metro Style Apps from C++ Developers' ViewMetro Style Apps from C++ Developers' View
Metro Style Apps from C++ Developers' View
Eric ShangKuan
 
Tuning Web Performance
Tuning Web PerformanceTuning Web Performance
Tuning Web Performance
Eric ShangKuan
 

More from Eric ShangKuan (13)

運用 Azure Custom Vision 輕鬆開發智慧視覺應用程式
運用 Azure Custom Vision 輕鬆開發智慧視覺應用程式運用 Azure Custom Vision 輕鬆開發智慧視覺應用程式
運用 Azure Custom Vision 輕鬆開發智慧視覺應用程式
 
Azure machine learning overview
Azure machine learning overviewAzure machine learning overview
Azure machine learning overview
 
Internet Explorer 10: 重新想像網站設計
Internet Explorer 10: 重新想像網站設計Internet Explorer 10: 重新想像網站設計
Internet Explorer 10: 重新想像網站設計
 
透過 Windows Azure Mobile Services 開發各平台 Apps
透過 Windows Azure Mobile Services 開發各平台 Apps透過 Windows Azure Mobile Services 開發各平台 Apps
透過 Windows Azure Mobile Services 開發各平台 Apps
 
Metro Style Apps from C++ Developers' View
Metro Style Apps from C++ Developers' ViewMetro Style Apps from C++ Developers' View
Metro Style Apps from C++ Developers' View
 
Building Python Applications on Windows Azure
Building Python Applications on Windows AzureBuilding Python Applications on Windows Azure
Building Python Applications on Windows Azure
 
Microsoft and jQuery
Microsoft and jQueryMicrosoft and jQuery
Microsoft and jQuery
 
Tuning Web Performance
Tuning Web PerformanceTuning Web Performance
Tuning Web Performance
 
Intro To Google Maps
Intro To Google MapsIntro To Google Maps
Intro To Google Maps
 
An Introduction to GAEO web framework
An Introduction to GAEO web frameworkAn Introduction to GAEO web framework
An Introduction to GAEO web framework
 
Intro. to JavaScript
Intro. to JavaScriptIntro. to JavaScript
Intro. to JavaScript
 
Intro. to CSS
Intro. to CSSIntro. to CSS
Intro. to CSS
 
jQuery Tutorial
jQuery TutorialjQuery Tutorial
jQuery Tutorial
 

Recently uploaded

Recently uploaded (20)

Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 

Practical Google App Engine Applications In Py

  • 1. Practical Google App Engine Applications in Python 上官林傑 (ericsk) COSCUP 2009 http://tinyurl.com/coscup-appengine
  • 2. Outline Effective Datastore API Data Manipulation Efficiency Effective Memcache Zip Import & Zip Serve Conclusion
  • 3. Quota Limit on App Engine from: http://www.flickr.com/photos/kevin814/3587610731/
  • 4. What's Datastore Datastore is a kind of key-value database built on GFS. scalable Kind-based data entities. (not table-based) add/remove properties dynamically Relational DB Table Datastore
  • 5. Avoid Heavily-Indexing Datastore will create index on each property. If there're many properties in your data, indexing will downgrade performance. If a property is not used for filtering nor ordering, add indexed=False to the data model declaration. class Foo(db.Model): name = db.StringProperty(required=True) bar = db.StringProperty(indexed=False)
  • 6. Minimize Datastore API Calls CRUD data entities by keys: Ineffective Way: keys = [key1, key2, key3, ..., keyN] products = [] for key in keys: products.append(db.get(key)) ... Effective Way: keys = [key1, key2, key3, ..., keyN] products = db.get(keys) Same as db.put(), db.delete().
  • 7. Re-bind GqlQuery Object Use prepared GqlQuery data: Ineffective way: conds = [['abc', 'def'], ['123', '456'], ...] for cond in conds: query = db.GqlQuery('SELECT * FROM Foo WHERE first = : first, second = :second', first=cond[0], second=cond[1]) .... Effective way: conds = [['abc', 'def'], ['123', '456'], ...] prepared_query = db.GqlQuery('SELECT * FROM Foo WHERE first = :first, second = :second') for cond in conds: query = prepared_query.bind(first=cond[0], second=cond [1]) ....
  • 8. Avoid Disjunctions IN or != operator generates more queries. SELECT * FROM Foo WHERE a IN ('x', 'y') and b != 3 splits into 4 queries SELECT * FROM Foo WHERE a == 'x' SELECT * FROM Foo WHERE a == 'y' SELECT * FROM Foo WHERE b < 3 SELECT * FROM Foo WHERE b > 3 Fetches all data and filters them manually.
  • 9. How to Fetch More Than 1000 Results Datastore API fetches no more than 1000 results once a call Fetches more than 1000 results (SLOW, may cause TLE) data = Foo.gql('ORDER BY __key__').fetch(1000) last_key = data[-1].key() results = data while len(data) == 1000: data = Foo.gql('WHERE __key__ > :1 ORDER BY __key__', last_key).fetch(1000) last_key = data[-1].key() results.extend(data)
  • 10. Put Data into Entity Group
  • 11. Put Data into Entity Group (cont.) Put data into an entity group: forum = Forum.get_by_key_name('HotForum') topic = Topic(key_name='Topic1',......, parent=forum).put() Load data from an entity group: topic = Topic.get_by_key_name('Topic1', parent=db.Key.from_path('Forum', 'HotForum'))
  • 12. Sharding Data Write data in parallel avoiding write contention Sharding data with key_name: class Counter(db.Model): name = db.StringProperty() count = db.IntegerProperty() ... def incr_counter(counter_name): shard = random.randint(0, NUM_SHARDS - 1) counter = Counter.get_or_insert(shard, name=counter_name) counter.count += 1 counter.put()
  • 13. Effective Caching Caching page content Without caching .... self.response.out.write( template.render('index.html', {}) ) ... With Caching page_content = memcache.get('index_page_content') if page_content is None: page_content = template.render('index.html',{}) self.response.out.write(page_content)
  • 14. Effective Caching (cont.) Caching frequently fetched entities Without caching .... products = Product.gql('WHERE price < 100').fetch(1000) from django.utils import simplejson self.response.out.write(simplejson.dumps(products)) With caching ... products = memcache.get('products_lt_100') if products is None: products = Product.gql('WHERE price < 100').fetch(1000) from django.utils import simplejson self.response.out.write(simplejson.dumps(products))
  • 15. Zipimport & ZipServe ZipImport: Zip your library and then import modules within it. ZipServe: Zip your static/asset files, then serve them with zipserve. WHY? You can ONLY put 1000 files in your application.
  • 16. Zipimport For example, you want to use Google Data client library in your application. You have to put gdata/ and atom/ packages into your application directory. With zipimport, you can zip them: application/ app.yaml .... atom.zip gdata.zip ....
  • 17. Zipimport (cont.) import gdata modules in your script: ... import sys sys.path.append('atom.zip') sys.path.append('gdata.zip') .... from gdata.doc import service
  • 18. Zipserve For example, you want to use TinyMCE library You have to put TinyMCE library into your directory. However, it contains lots of files. With zipserve, you can zip the library, and configure the app. yaml: ... - url: /tinymce/.* script: $PYTHON_LIB/google/appengine/ext/zipserve The filename MUST be the same as the directory name. In this sample, the TinyMCE library should be zipped into tinymce. zip.
  • 19. Conclusion - How to Write Better GAE Apps? Read the Articles on Google App Engine site. Trace the source from SDK Maybe you will find the undocumented API. Read http://practicalappengine.blogspot.com/ (in Traditional Chinese) Develop apps!