GAE Meets Django
Upcoming SlideShare
Loading in...5
×
 

GAE Meets Django

on

  • 2,503 views

 

Statistics

Views

Total Views
2,503
Views on SlideShare
2,423
Embed Views
80

Actions

Likes
2
Downloads
41
Comments
0

5 Embeds 80

http://www.onlypython.com 61
http://onlypython.appspot.com 16
http://3.1.onlypython.appspot.com 1
http://www.slideshare.net 1
http://2.2.onlypython.appspot.com 1

Accessibility

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

GAE Meets Django GAE Meets Django Presentation Transcript

  • 使用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