SlideShare a Scribd company logo
1 of 37
Download to read offline
Django
Google App Engine


    linsheng.cn@gmail.com
• Google App Engine
• Django
•
Google App Engine
Google App Engine
• Google   Web Hosting

•      Web               Google

•                    Scaling   load balancing

•

•      Google User         Gmail
• Python 2.5.2
•     Django 0.96.1                    CGI
                  CGI          WSGI

•       Sandbox
    socket          cron job

•                       response

•                Python            C
Datastore
•   Google BigTable

•                            ORM

•   Model

•
•     join, sum, avg

•                1000

•
App Engine Service

• Google

• Gmail         email

• URL Fetch
• Memcached
• Image (PIL)
(               )
Fixed Quota       Per Day Usage Quotas




                        500   PV/
• $0.10 - $0.12 per CPU core-hour
• $0.15 - $0.18 per GB-month of storage
• $0.11 - $0.13 per GB outgoing bandwidth
• $0.09 - $0.11 per GB incoming bandwidth
Google App Engine
• http://appengine.google.com/
•     Gmail

•

•     : http://yourapp.appspot.com

•          Google Apps
•     Web

•          idea,     startup

•     scalability

• App Gallery http://appgallery.appspot.com/
•

•

•

•

•   /
Django
Django

•            Python full-stack Web

• ORM, URL mapping, admin interface,
    template, middleware, i18n, cache...

•
Django              webapp

• Google App Engine Helper for Django
•

•
Blog

 OnlyPython
•       Google App Engine SDK
    http://code.google.com/appengine/downloads.html

•     SVN             Django
    http://code.djangoproject.com/svn/django/trunk/

•       Google App Engine Helper for Django
    http://code.google.com/p/google-app-engine-django/
--- appengine-django (app engine helper for django         )

--- django (django                 )

--- onlypy (               )

--- static (                           js, css,        )

--- app.yaml (app engine                   )

--- index.yaml (app engine                         )

--- main.py (app engine                        )

--- manage.py (Django                      )

--- settings.py (              )

--- urls.py (URL mapping)
app.yaml
  application:	
  onlypython
  version:	
  1
  runtime:	
  python
  api_version:	
  1
  handlers:
  -­‐	
  url:	
  /static
  static_dir:	
  static
  -­‐	
  url:	
  /.*
	
  	
  script:	
  main.py
main.py
import	
  os
import	
  sys
import	
  logging

from	
  appengine_django	
  import	
  InstallAppengineHelperForDjango
InstallAppengineHelperForDjango()

#	
  Google	
  App	
  Engine	
  imports.
from	
  google.appengine.ext.webapp	
  import	
  util

#	
  Import	
  the	
  part	
  of	
  Django	
  that	
  we	
  use	
  here.
import	
  django.core.handlers.wsgi

def	
  main():
	
  	
  #	
  Create	
  a	
  Django	
  application	
  for	
  WSGI.
	
  	
  application	
  =	
  django.core.handlers.wsgi.WSGIHandler()

	
  	
  #	
  Run	
  the	
  WSGI	
  CGI	
  handler	
  with	
  that	
  application.
	
  	
  util.run_wsgi_app(application)

if	
  __name__	
  ==	
  '__main__':
	
  	
  main()
settings.py
        TIME_ZONE	
  =	
  'UTC'
        MIDDLEWARE_CLASSES	
  =	
  (
        	
  	
  	
  	
  'django.middleware.common.CommonMiddleware',
        	
  	
  	
  	
  'appengine_django.auth.middleware.AuthenticationMiddleware',
        )
        ROOT_URLCONF	
  =	
  'urls'
        ROOT_PATH	
  =	
  os.path.dirname(__file__)
        TEMPLATE_DIRS	
  =	
  (
        	
  	
  	
  	
  os.path.join(ROOT_PATH,	
  'onlypy/templates')
        )
        INSTALLED_APPS	
  =	
  (
	
  	
  	
  	
  	
  'appengine_django',
	
  	
  	
  	
  	
  'django.contrib.auth',
	
  	
  	
  	
  	
  'onlypy.blog',
	
  	
  	
  )
TODO:   Blog
models.py
from	
  google.appengine.ext	
  import	
  db          	
  
class	
  Category(db.Model):
	
  	
  	
  	
  name	
  =	
  db.StringProperty()
	
  	
  	
  	
  
	
  	
  	
  	
  def	
  __str__(self):
	
  	
  	
  	
  	
  	
  	
  	
  return	
  self.name

class	
  Post(db.Model):
	
  	
  	
  	
  author	
  =	
  db.UserProperty()
	
  	
  	
  	
  title	
  =	
  db.StringProperty(required=True,	
  verbose_name=u'       ')
	
  	
  	
  	
  tag	
  =	
  db.StringProperty(verbose_name=u'       ')
	
  	
  	
  	
  content	
  =	
  db.TextProperty(required=True,	
  verbose_name=u'       ')
	
  	
  	
  	
  create_time	
  =	
  db.DateTimeProperty(auto_now_add=True)
	
  	
  	
  	
  update_time	
  =	
  db.DateTimeProperty(auto_now=True)
	
  	
  	
  	
  category	
  =	
  db.ReferenceProperty(Category,	
  required=True,	
  verbose_name=u'   ')
	
  	
  	
  	
  is_published	
  =	
  db.BooleanProperty(verbose_name=u'     ')
	
  	
  	
  	
  
	
  	
  	
  	
  def	
  get_absolute_url(self)	
  :
	
  	
  	
  	
  	
  	
  	
  	
  return	
  '/post/%s/'%self.key().id()
forms.py
from	
  google.appengine.ext.db	
  import	
  djangoforms	
  as	
  forms
from	
  models	
  import	
  Post

class	
  PostForm(forms.ModelForm):
	
  	
  	
  	
  class	
  Meta:
	
  	
  	
  	
  	
  	
  	
  	
  model	
  =	
  Post
	
  	
  	
  	
  	
  	
  	
  	
  exclude	
  =	
  ['author']
views.py
           def	
  add_post(request):
	
  	
  	
  	
  if	
  request.method	
  ==	
  'GET':
	
  	
  	
  	
  	
  	
  	
  	
  form	
  =	
  PostForm()
	
  	
  	
  	
  
	
  	
  	
  	
  if	
  request.method	
  ==	
  'POST':
	
  	
  	
  	
  	
  	
  	
  	
  form	
  =	
  PostForm(request.POST)
	
  	
  	
  	
  	
  	
  	
  	
  if	
  form.is_valid():
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  post	
  =	
  form.save()
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  post.author	
  =	
  users.get_current_user()
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  post.put()
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  HttpResponseRedirect('/post/add/')

	
  	
  	
  	
  return	
  render_to_response('blog/add_post.html',
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  {'form':	
  form},
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  context_instance=RequestContext(request))	
  
                                                                                                       	
  
add_post.html
{%	
  extends	
  "base.html"	
  %}

{%	
  block	
  content	
  %}
<h1>               </h1>
<form	
  name="mainForm"	
  method="post"	
  action="">
	
  	
  	
  	
  {{form.as_p}}
	
  	
  	
  	
  <input	
  type="submit"	
  value=" "/>
</form>
{%	
  endblock	
  %}
urls.py
from	
  django.conf.urls.defaults	
  import	
  *

urlpatterns	
  =	
  patterns('onlypy.blog.views',
	
  	
  	
  	
  (r'^post/add/$',	
  'add_post'),
)
Run
• cd /yourpath/onlypython/
• python ./manage.py runserver 127.0.0.1:8000
http://localhost:8000/post/add/
TODO:   Blog
views.py
    def	
  list_post(request):

	
  	
  	
  	
  posts	
  =	
  Post.all().order('-­‐create_time')
	
  	
  	
  	
  if	
  (not	
  is_admin()):
	
  	
  	
  	
  	
  	
  	
  	
  posts	
  =	
  posts.filter("is_published",	
  True)
	
  	
  	
  	
  
	
  	
  	
  	
  return	
  object_list(request,	
  queryset=posts,	
  allow_empty=True,
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  template_name='blog/list_post.html',	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  extra_context={'is_admin':	
  is_admin()},
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  paginate_by=20)	
  	
  
index.yaml
        indexes:
	
  	
  	
  	
  -­‐	
  kind:	
  Post
	
  	
  	
  	
  	
  	
  properties:
	
  	
  	
  	
  	
  	
  -­‐	
  name:	
  is_published
	
  	
  	
  	
  	
  	
  -­‐	
  name:	
  create_time
	
  	
  	
  	
  	
  	
  	
  	
  direction:	
  desc
list_post.html
{%	
  extends	
  "base.html"	
  %}
{%	
  load	
  markup	
  %}
{%	
  load	
  paginator	
  %}

{%	
  block	
  content	
  %}
{%	
  for	
  post	
  in	
  object_list	
  %}
	
  
<table	
  border="0"	
  cellspacing="0"	
  cellpadding="0"	
  width="100%">
	
  	
  	
  	
  <tr>
	
  	
  	
  	
  	
  	
  	
  	
  <td	
  valign="top">
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  <h1	
  style="margin-­‐bottom:	
  2px;">
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  <a	
  href="/post/{{post.key.id}}">
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  [{{	
  post.category.name	
  }}]	
  {{	
  post.title	
  }}{%	
  if	
  post.is_published	
  %}
{%else%}(                                                 ){%endif%}
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  </a>
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  </h1>
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  <p	
  style="padding:0px;	
  margin:	
  0px;"	
  class="small_font">
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
      :	
  <a	
  href="/category/{{	
  post.category.key.id	
  }}/">
{{	
  post.category.name	
  }}</a>	
  <span	
  style="padding-­‐left:	
  10px;">{{	
  post.author.nickname	
  }}
       {{	
  post.create_time|date:"Y-­‐M-­‐d	
  H:i"	
  }}</span>
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  </p>
	
  	
  	
  	
  	
  	
  	
  	
  </td>
	
  	
  	
  	
  </tr>
</table>
<div	
  style="padding-­‐left:	
  30px;">
	
  	
  	
  	
  {{	
  post.content|markdown	
  }}
</div>
{%	
  endfor	
  %}
{%	
  paginator	
  %}
{%	
  endblock	
  %}
urls.py
from	
  django.conf.urls.defaults	
  import	
  *

urlpatterns	
  =	
  patterns('onlypy.blog.views',
	
  	
  	
  	
  (r'^post/add/$',	
  'add_post'),
	
  	
  	
  	
  (r'^$',	
  'list_post'),
)
http://localhost:8000/
•   http://code.google.com/p/onlypy/

•   http://www.onlypython.com
Q&A

More Related Content

What's hot

Build and deploy Python Django project
Build and deploy Python Django projectBuild and deploy Python Django project
Build and deploy Python Django projectXiaoqi Zhao
 
AtlasCamp 2015: Connect everywhere - Cloud and Server
AtlasCamp 2015: Connect everywhere - Cloud and ServerAtlasCamp 2015: Connect everywhere - Cloud and Server
AtlasCamp 2015: Connect everywhere - Cloud and ServerAtlassian
 
AtlasCamp 2015: Web technologies you should be using now
AtlasCamp 2015: Web technologies you should be using nowAtlasCamp 2015: Web technologies you should be using now
AtlasCamp 2015: Web technologies you should be using nowAtlassian
 
Mezzanine簡介 (at) Taichung.py
Mezzanine簡介 (at) Taichung.pyMezzanine簡介 (at) Taichung.py
Mezzanine簡介 (at) Taichung.pyMax Lai
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecturepostrational
 
Dynamic Business Processes using Automated Actions
Dynamic Business Processes using Automated ActionsDynamic Business Processes using Automated Actions
Dynamic Business Processes using Automated ActionsDaniel Reis
 
Plug in development
Plug in developmentPlug in development
Plug in developmentLucky Ali
 
Course CodeSchool - Shaping up with Angular.js
Course CodeSchool - Shaping up with Angular.jsCourse CodeSchool - Shaping up with Angular.js
Course CodeSchool - Shaping up with Angular.jsVinícius de Moraes
 
Basic Crud In Django
Basic Crud In DjangoBasic Crud In Django
Basic Crud In Djangomcantelon
 
Build Amazing Add-ons for Atlassian JIRA and Confluence
Build Amazing Add-ons for Atlassian JIRA and ConfluenceBuild Amazing Add-ons for Atlassian JIRA and Confluence
Build Amazing Add-ons for Atlassian JIRA and ConfluenceK15t
 
Tips and Tricks for LiveWhale Development
Tips and Tricks for LiveWhale DevelopmentTips and Tricks for LiveWhale Development
Tips and Tricks for LiveWhale DevelopmentNaomi Royall
 
Caldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW WorkshopCaldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW WorkshopCalderaLearn
 
243329387 angular-docs
243329387 angular-docs243329387 angular-docs
243329387 angular-docsAbhi166803
 
Action Controller Overview, Season 2
Action Controller Overview, Season 2Action Controller Overview, Season 2
Action Controller Overview, Season 2RORLAB
 
Introduction to django
Introduction to djangoIntroduction to django
Introduction to djangoIlian Iliev
 

What's hot (20)

Build and deploy Python Django project
Build and deploy Python Django projectBuild and deploy Python Django project
Build and deploy Python Django project
 
AtlasCamp 2015: Connect everywhere - Cloud and Server
AtlasCamp 2015: Connect everywhere - Cloud and ServerAtlasCamp 2015: Connect everywhere - Cloud and Server
AtlasCamp 2015: Connect everywhere - Cloud and Server
 
AtlasCamp 2015: Web technologies you should be using now
AtlasCamp 2015: Web technologies you should be using nowAtlasCamp 2015: Web technologies you should be using now
AtlasCamp 2015: Web technologies you should be using now
 
Mezzanine簡介 (at) Taichung.py
Mezzanine簡介 (at) Taichung.pyMezzanine簡介 (at) Taichung.py
Mezzanine簡介 (at) Taichung.py
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecture
 
Dynamic Business Processes using Automated Actions
Dynamic Business Processes using Automated ActionsDynamic Business Processes using Automated Actions
Dynamic Business Processes using Automated Actions
 
Gae
GaeGae
Gae
 
Plug in development
Plug in developmentPlug in development
Plug in development
 
Apex & jQuery Mobile
Apex & jQuery MobileApex & jQuery Mobile
Apex & jQuery Mobile
 
Course CodeSchool - Shaping up with Angular.js
Course CodeSchool - Shaping up with Angular.jsCourse CodeSchool - Shaping up with Angular.js
Course CodeSchool - Shaping up with Angular.js
 
Basic Crud In Django
Basic Crud In DjangoBasic Crud In Django
Basic Crud In Django
 
Build Amazing Add-ons for Atlassian JIRA and Confluence
Build Amazing Add-ons for Atlassian JIRA and ConfluenceBuild Amazing Add-ons for Atlassian JIRA and Confluence
Build Amazing Add-ons for Atlassian JIRA and Confluence
 
Tips and Tricks for LiveWhale Development
Tips and Tricks for LiveWhale DevelopmentTips and Tricks for LiveWhale Development
Tips and Tricks for LiveWhale Development
 
Caldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW WorkshopCaldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW Workshop
 
实战Ecos
实战Ecos实战Ecos
实战Ecos
 
Angular js
Angular jsAngular js
Angular js
 
243329387 angular-docs
243329387 angular-docs243329387 angular-docs
243329387 angular-docs
 
Angular js
Angular jsAngular js
Angular js
 
Action Controller Overview, Season 2
Action Controller Overview, Season 2Action Controller Overview, Season 2
Action Controller Overview, Season 2
 
Introduction to django
Introduction to djangoIntroduction to django
Introduction to django
 

Viewers also liked

Teaching an Old Pony New Tricks: Maintaining and Updating and Aging Django Site
Teaching an Old Pony New Tricks: Maintaining and Updating and Aging Django SiteTeaching an Old Pony New Tricks: Maintaining and Updating and Aging Django Site
Teaching an Old Pony New Tricks: Maintaining and Updating and Aging Django SiteShawn Rider
 
Agile Development with Plone
Agile Development with PloneAgile Development with Plone
Agile Development with PloneJazkarta, Inc.
 
Plone in Higher Education
Plone in Higher EducationPlone in Higher Education
Plone in Higher EducationJazkarta, Inc.
 
Gtd Intro
Gtd IntroGtd Intro
Gtd Introfool2nd
 

Viewers also liked (6)

Pinax
PinaxPinax
Pinax
 
DjangoCon recap
DjangoCon recapDjangoCon recap
DjangoCon recap
 
Teaching an Old Pony New Tricks: Maintaining and Updating and Aging Django Site
Teaching an Old Pony New Tricks: Maintaining and Updating and Aging Django SiteTeaching an Old Pony New Tricks: Maintaining and Updating and Aging Django Site
Teaching an Old Pony New Tricks: Maintaining and Updating and Aging Django Site
 
Agile Development with Plone
Agile Development with PloneAgile Development with Plone
Agile Development with Plone
 
Plone in Higher Education
Plone in Higher EducationPlone in Higher Education
Plone in Higher Education
 
Gtd Intro
Gtd IntroGtd Intro
Gtd Intro
 

Similar to Gae Meets Django

Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to DjangoJoaquim Rocha
 
GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineYared Ayalew
 
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)Python Ireland
 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010ikailan
 
Django for Beginners
Django for BeginnersDjango for Beginners
Django for BeginnersJason Davies
 
Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4DEVCON
 
國民雲端架構 Django + GAE
國民雲端架構 Django + GAE國民雲端架構 Django + GAE
國民雲端架構 Django + GAEWinston Chen
 
The Big Picture and How to Get Started
The Big Picture and How to Get StartedThe Big Picture and How to Get Started
The Big Picture and How to Get Startedguest1af57e
 
WordPress as the Backbone(.js)
WordPress as the Backbone(.js)WordPress as the Backbone(.js)
WordPress as the Backbone(.js)Beau Lebens
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to DjangoJames Casey
 
Hands on django part 1
Hands on django part 1Hands on django part 1
Hands on django part 1MicroPyramid .
 

Similar to Gae Meets Django (20)

Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to Django
 
Django Vs Rails
Django Vs RailsDjango Vs Rails
Django Vs Rails
 
GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App Engine
 
Django
DjangoDjango
Django
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to Django
 
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)
 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010
 
Django crush course
Django crush course Django crush course
Django crush course
 
Django for Beginners
Django for BeginnersDjango for Beginners
Django for Beginners
 
Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
 
國民雲端架構 Django + GAE
國民雲端架構 Django + GAE國民雲端架構 Django + GAE
國民雲端架構 Django + GAE
 
The Big Picture and How to Get Started
The Big Picture and How to Get StartedThe Big Picture and How to Get Started
The Big Picture and How to Get Started
 
WordPress as the Backbone(.js)
WordPress as the Backbone(.js)WordPress as the Backbone(.js)
WordPress as the Backbone(.js)
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to Django
 
Hands on django part 1
Hands on django part 1Hands on django part 1
Hands on django part 1
 

Gae Meets Django

  • 1. Django Google App Engine linsheng.cn@gmail.com
  • 2. • Google App Engine • Django •
  • 4. Google App Engine • Google Web Hosting • Web Google • Scaling load balancing • • Google User Gmail
  • 5. • Python 2.5.2 • Django 0.96.1 CGI CGI WSGI • Sandbox socket cron job • response • Python C
  • 6. Datastore • Google BigTable • ORM • Model • • join, sum, avg • 1000 •
  • 7. App Engine Service • Google • Gmail email • URL Fetch • Memcached • Image (PIL)
  • 8. ( ) Fixed Quota Per Day Usage Quotas 500 PV/
  • 9. • $0.10 - $0.12 per CPU core-hour • $0.15 - $0.18 per GB-month of storage • $0.11 - $0.13 per GB outgoing bandwidth • $0.09 - $0.11 per GB incoming bandwidth
  • 10. Google App Engine • http://appengine.google.com/ • Gmail • • : http://yourapp.appspot.com • Google Apps
  • 11. Web • idea, startup • scalability • App Gallery http://appgallery.appspot.com/
  • 14. Django • Python full-stack Web • ORM, URL mapping, admin interface, template, middleware, i18n, cache... •
  • 15. Django webapp • Google App Engine Helper for Django • •
  • 17. Google App Engine SDK http://code.google.com/appengine/downloads.html • SVN Django http://code.djangoproject.com/svn/django/trunk/ • Google App Engine Helper for Django http://code.google.com/p/google-app-engine-django/
  • 18. --- appengine-django (app engine helper for django ) --- django (django ) --- onlypy ( ) --- static ( js, css, ) --- app.yaml (app engine ) --- index.yaml (app engine ) --- main.py (app engine ) --- manage.py (Django ) --- settings.py ( ) --- urls.py (URL mapping)
  • 19. app.yaml application:  onlypython version:  1 runtime:  python api_version:  1 handlers: -­‐  url:  /static static_dir:  static -­‐  url:  /.*    script:  main.py
  • 20. main.py import  os import  sys import  logging from  appengine_django  import  InstallAppengineHelperForDjango InstallAppengineHelperForDjango() #  Google  App  Engine  imports. from  google.appengine.ext.webapp  import  util #  Import  the  part  of  Django  that  we  use  here. import  django.core.handlers.wsgi def  main():    #  Create  a  Django  application  for  WSGI.    application  =  django.core.handlers.wsgi.WSGIHandler()    #  Run  the  WSGI  CGI  handler  with  that  application.    util.run_wsgi_app(application) if  __name__  ==  '__main__':    main()
  • 21. settings.py TIME_ZONE  =  'UTC' MIDDLEWARE_CLASSES  =  (        'django.middleware.common.CommonMiddleware',        'appengine_django.auth.middleware.AuthenticationMiddleware', ) ROOT_URLCONF  =  'urls' ROOT_PATH  =  os.path.dirname(__file__) TEMPLATE_DIRS  =  (        os.path.join(ROOT_PATH,  'onlypy/templates') ) INSTALLED_APPS  =  (          'appengine_django',          'django.contrib.auth',          'onlypy.blog',      )
  • 22. TODO: Blog
  • 23. models.py from  google.appengine.ext  import  db   class  Category(db.Model):        name  =  db.StringProperty()                def  __str__(self):                return  self.name class  Post(db.Model):        author  =  db.UserProperty()        title  =  db.StringProperty(required=True,  verbose_name=u' ')        tag  =  db.StringProperty(verbose_name=u' ')        content  =  db.TextProperty(required=True,  verbose_name=u' ')        create_time  =  db.DateTimeProperty(auto_now_add=True)        update_time  =  db.DateTimeProperty(auto_now=True)        category  =  db.ReferenceProperty(Category,  required=True,  verbose_name=u' ')        is_published  =  db.BooleanProperty(verbose_name=u' ')                def  get_absolute_url(self)  :                return  '/post/%s/'%self.key().id()
  • 24. forms.py from  google.appengine.ext.db  import  djangoforms  as  forms from  models  import  Post class  PostForm(forms.ModelForm):        class  Meta:                model  =  Post                exclude  =  ['author']
  • 25. views.py def  add_post(request):        if  request.method  ==  'GET':                form  =  PostForm()                if  request.method  ==  'POST':                form  =  PostForm(request.POST)                if  form.is_valid():                        post  =  form.save()                        post.author  =  users.get_current_user()                        post.put()                        return  HttpResponseRedirect('/post/add/')        return  render_to_response('blog/add_post.html',                              {'form':  form},                              context_instance=RequestContext(request))    
  • 26. add_post.html {%  extends  "base.html"  %} {%  block  content  %} <h1> </h1> <form  name="mainForm"  method="post"  action="">        {{form.as_p}}        <input  type="submit"  value=" "/> </form> {%  endblock  %}
  • 27. urls.py from  django.conf.urls.defaults  import  * urlpatterns  =  patterns('onlypy.blog.views',        (r'^post/add/$',  'add_post'), )
  • 28. Run • cd /yourpath/onlypython/ • python ./manage.py runserver 127.0.0.1:8000
  • 30. TODO: Blog
  • 31. views.py def  list_post(request):        posts  =  Post.all().order('-­‐create_time')        if  (not  is_admin()):                posts  =  posts.filter("is_published",  True)                return  object_list(request,  queryset=posts,  allow_empty=True,                                template_name='blog/list_post.html',                                  extra_context={'is_admin':  is_admin()},                                paginate_by=20)    
  • 32. index.yaml indexes:        -­‐  kind:  Post            properties:            -­‐  name:  is_published            -­‐  name:  create_time                direction:  desc
  • 33. list_post.html {%  extends  "base.html"  %} {%  load  markup  %} {%  load  paginator  %} {%  block  content  %} {%  for  post  in  object_list  %}   <table  border="0"  cellspacing="0"  cellpadding="0"  width="100%">        <tr>                <td  valign="top">                        <h1  style="margin-­‐bottom:  2px;">                                <a  href="/post/{{post.key.id}}">                                        [{{  post.category.name  }}]  {{  post.title  }}{%  if  post.is_published  %} {%else%}( ){%endif%}                                </a>                        </h1>                        <p  style="padding:0px;  margin:  0px;"  class="small_font">                                 :  <a  href="/category/{{  post.category.key.id  }}/"> {{  post.category.name  }}</a>  <span  style="padding-­‐left:  10px;">{{  post.author.nickname  }} {{  post.create_time|date:"Y-­‐M-­‐d  H:i"  }}</span>                        </p>                </td>        </tr> </table> <div  style="padding-­‐left:  30px;">        {{  post.content|markdown  }} </div> {%  endfor  %} {%  paginator  %} {%  endblock  %}
  • 34. urls.py from  django.conf.urls.defaults  import  * urlpatterns  =  patterns('onlypy.blog.views',        (r'^post/add/$',  'add_post'),        (r'^$',  'list_post'), )
  • 36. http://code.google.com/p/onlypy/ • http://www.onlypython.com
  • 37. Q&A