gae meets django

37
使用DjangoGoogle App Engine[email protected]

Upload: fool2nd

Post on 14-May-2015

3.186 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Gae Meets Django

使用Django创建Google App Engine应用

林胜[email protected]

Page 2: Gae Meets Django

• Google App Engine介绍

• Django介绍

• 代码示例

Page 3: Gae Meets Django

Google App Engine介绍

Page 4: Gae Meets Django

什么是Google App Engine• Google的Web Hosting服务

•将你的Web应用部署到Google的基础设施之上

•使你的应用能够自动Scaling和load balancing

•提供数据存储服务

•集成了Google User认证和Gmail等服务

Page 5: Gae Meets Django

运行环境和限制• Python 2.5.2

•内置Django 0.96.1,并支持所有支持CGI的框架(以及任何使用CGI适配器的WSGI框架)

•运行在Sandbox中,不能访问文件系统,不能建立socket,不支持cron job,不能创建子进程

•限定时间内必须返回response

•应用必须是纯Python,不支持C的扩展

Page 6: Gae Meets Django

存储-Datastore•基于Google BigTable,分布式存储服务

•面向对象,非关系型数据库,不支持ORM

•相同Model可以有不同的属性

•支持查询,排序,事务

•不支持join, sum, avg等,不支持存储过程

•每次查询最多返回1000条记录

•全文检索?

Page 7: Gae Meets Django

App Engine Service

• Google帐号认证

• Gmail(发送email)

• URL Fetch

• Memcached

• Image (PIL)

Page 8: Gae Meets Django

价格(免费部分)Fixed Quota Per Day Usage Quotas

大约500万PV/月

Page 9: Gae Meets Django

价格(收费部分)

• $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

Page 10: Gae Meets Django

申请Google App Engine• http://appengine.google.com/

•通过Gmail帐号

•通过短信认证

•域名: http://yourapp.appspot.com

•可以通过Google Apps绑定自己的域名

Page 11: Gae Meets Django

用途

•学习Web开发

•尝试各种idea, 减少startup的前期投入成本

•解决scalability问题

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

Page 12: Gae Meets Django

未来计划•对更多语言的支持

•收费计划

•大数据量的上传和下载

•离线处理

•数据导入/导出

Page 13: Gae Meets Django

Django简介

Page 14: Gae Meets Django

Django简介

•一个基于Python的full-stack Web框架

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

•很快很强大

Page 15: Gae Meets Django

为什么用Django(而不是webapp)

• Google App Engine Helper for Django

•功能更强大

•可移植性

Page 16: Gae Meets Django

项目示例-Blog系统

项目名称 - OnlyPython

Page 17: Gae Meets Django

创建开发环境

• 下载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/

Page 18: Gae Meets 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)

Page 19: Gae Meets Django

app.yamlapplication:  onlypython

version:  1

runtime:  python

api_version:  1

handlers:

-­‐  url:  /static

static_dir:  static

-­‐  url:  /.*

   script:  main.py

Page 20: Gae Meets Django

main.pyimport  osimport  sysimport  logging

from  appengine_django  import  InstallAppengineHelperForDjangoInstallAppengineHelperForDjango()

#  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()

Page 21: Gae Meets Django

settings.pyTIME_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',

     )

Page 22: Gae Meets Django

TODO: 添加Blog

Page 23: Gae Meets Django

models.pyfrom  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()

Page 24: Gae Meets Django

forms.pyfrom  google.appengine.ext.db  import  djangoforms  as  formsfrom  models  import  Post

class  PostForm(forms.ModelForm):        class  Meta:                model  =  Post                exclude  =  ['author']

Page 25: Gae Meets Django

views.pydef  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))    

Page 26: Gae Meets Django

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  %}

Page 27: Gae Meets Django

urls.pyfrom  django.conf.urls.defaults  import  *

urlpatterns  =  patterns('onlypy.blog.views',        (r'^post/add/$',  'add_post'),)

Page 28: Gae Meets Django

Run• cd /yourpath/onlypython/

• python ./manage.py runserver 127.0.0.1:8000

Page 30: Gae Meets Django

TODO: 显示Blog列表

Page 31: Gae Meets Django

views.pydef  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)    

Page 32: Gae Meets Django

index.yamlindexes:

       -­‐  kind:  Post            properties:            -­‐  name:  is_published            -­‐  name:  create_time                direction:  desc

Page 33: Gae Meets Django

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  %}

Page 34: Gae Meets Django

urls.pyfrom  django.conf.urls.defaults  import  *

urlpatterns  =  patterns('onlypy.blog.views',        (r'^post/add/$',  'add_post'),        (r'^$',  'list_post'),)

Page 36: Gae Meets Django

项目信息• 项目代码 http://code.google.com/p/onlypy/

• 项目演示 http://www.onlypython.com

Page 37: Gae Meets Django

Q&A