
于2009-05-03 13:51:00翻译 | 已有2641人浏览
利用app-engine-patch在appengine中使用Django.
介绍
在Django框架可以让一个web开发者的生活为更轻松。它照顾到了很多Web开发者所必须处理的共同问题,并提供了许多“可服用的组件” -您可以插入到您的项目重的严格测试过的代码。
由于一些概念上的差异,一些Django特性不能在Google App Engine上工作。其中一个主要的特性就是Django的ORM,因为AppEngine的数据存储(Datastore)不同于Django的ORM所基于的传统的关系数据库模型。app-engine-patch是一个围绕在缺乏对Django ORM的支持所带来的限制之上,旨在提供Django所具有的全部功能的项目。该项目可以在这里找到:http://code.google.com/p/app-engine-patch/
App-engine-patch 需要 the App Engine SDK 才能工作: http://code.google.com/appengine/downloads.html.__init__.py - Python会把包含这个文件的文件夹视为一个包urls.py - 特定应用的URL配置.它控制在给定的URL上执行视图(请求处理request handlers) models.py - 应用的数据存储模型 views.py - 包含视图,Django中处理请求逻辑的术语 templates - 包含你的应用的HTML模板的文件夹INSTALLED_APPS列表中把你的应用名称包含进来:INSTALLED_APPS =(
...
'guestbook',
)
urlpatterns = patterns('',
...
(r'^guestbook/', include('guestbook.urls')),
)
现在如果你访问任何以/guestbook/开头的网址,系统将会在应用特定URL配置文件/guestbook/urls.py中寻找匹配的请求。
创建models
打开你的/guestbook/models文件,创建如下的数据库模型:
from google.appengine.ext import db
from django.contrib.auth.models importUser
classGreeting(db.Model):
author = db.ReferenceProperty(User)
content = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
用户model将会由app-engine-patch给我妈提供,所以这里不必特意指定了。因为我们希望Django和Google用户认证可以
生效,所以需要在你的设置中激活中间件并制定正确的用户model.在/settings.py中替换Django的认证中间件:
# Replace Django's AuthenticationMiddleware with HybridAuthenticationMiddleware.
MIDDLEWARE_CLASSES =(
...
'ragendja.auth.middleware.HybridAuthenticationMiddleware',
...
)
并添加
# Change the User model class
AUTH_USER_MODULE ='ragendja.auth.hybrid_models'
# Add google_login_url and google_logout_url tags
GLOBALTAGS =('ragendja.templatetags.googletags',)
到文件的末尾。
这就是一切。真不敢相信,但这是真的!现在你已经可以同时使用Django和Google的用户认证了。另外,你还可以启用模板标记
以渲染随时出现的Google登录和注销链接。要尝试的话,创建一个/guestbook/templates/index.html文件
<html>
<head>
</head>
<body>compliant
<divclass="login">
{% if user.is_authenticated %}
Welcome, {{ user.username }}
<ahref="{% google_logout_url request.get_full_path %}">Logout</a>
{% else %}
<ahref="{% google_login_url request.get_full_path %}">Login</a>
{% endif %}
</div>
</body>
</html>
并且在/guestbook/urls.py中设置URL路由:
from django.conf.urls.defaults import*
如果你现在在浏览器中加载http://localhost:8000/guestbook/,你要看到google认证的请求。不难吧?
注意: 这里你通过渲染html模板的同时也见到了Django的generic views是如何生效的.
提供非Google用户的认证
现在让我们为没有Google账户的人员添加认证.我们再次将尽可能的利用generic views,因为使用他们更简单而且比你自己手写
views出错的可能性更小。
第一件事情就是让用户可以登录,还记得我们在settings.py中设置的AUTH_USER_MODULE指令么?这将执行一些魔力,使我们能够
导入通常的Django 用户model,而且还有混合身份验证的支持。
注册用户
为了让用户可以注册账户,在/guestbook/views.py中添加如下代码:
from django.contrib.auth.models importUser
from django.contrib.auth.forms importUserCreationForm
from django.shortcuts import render_to_response
from django.http importHttpResponseRedirect
def create_new_user(request):
form =UserCreationForm()
# if form was submitted, bind form instance.
if request.method =='POST':
form =UserCreationForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
# user must be active for login to work
user.is_active =True
user.put()
returnHttpResponseRedirect('/guestbook/login/')
return render_to_response('guestbook/user_create_form.html',{'form': form})
这里我不会去讲太多细节,因为它实际上与标准Django没什么区别。app-engine-patch在幕后处理了创建用户的细节,包括使用
App Engine的datastore代替通常Django中使用的数据库表。
UserCreationForm自动由Django提供。这个view创建了一个表单对象,并把它传给一个叫user_create_form.html的模板。
当一个表单通过POST请求提交后,一个用户被创建,接着用户将被重定向到登录页面。如果表单是无效的,将提供一个有意义的错误信息
提示.
为了看到这个操作,还有两件事得做。首先把"create_new_user方法挂到你的URL配置文件/guestbook/urls.py中去:
urlpatterns = patterns('',
...
(r'^signup/$','guestbook.views.create_new_user'),
)
并创建一个模板/guestbook/templates/user_create_form.html:
<html>
<head>
</head>
<body>
<formaction="."method="post">
<table>
{{form.as_table}}
</table>
You can also login with your <ahref="{% google_login_url "/guestbook" %}">Google account.</a>
<inputtype="submit"value="submit">
</form>
</body>
</html>
Django用户登录
urlpatterns = patterns('',
...
(r'^login/$','django.contrib.auth.views.login',{'template_name':'guestbook/user_create_form.html'}),
)
http://localhost:8000/guestbook/login/ 看看generic view是如何生效的。LOGIN_REDIRECT_URL = "/guestbook/"来改变它,不然登陆的用户将会看到404消息页面.#the "logout" generic view expects a template logged_out.html. Using this generic view, you can redirect the user to
#another page after log out.
(r'^logout/$','django.contrib.auth.views.logout_then_login',{'login_url':'/guestbook/'}),
并且替换/guestbook/templates/index.html 如下:
{%if user.is_active %}<a href="/guestbook/logout">
{%else%}<a href="{% google_logout_url "/guestbook/" %}">
{% endif %}Logout</a>
因为Google用户没有 is_active 这个域,所以上述例子可以生效。存在一些更好的方法检查我们正在处理的是哪一类型的用户,但是对于我们
的案例来说这个更简单并且可以工作。app-engine-patch的库版本中包括区分不同用户类型的方法。
让guestbook工作
现在让我们添加创建和显示guestbook条目的能力。添加如下代码到/guestbook/views.py的末尾:
from django.views.generic.list_detail import object_list
from django.views.generic.create_update import create_object
from django.contrib.auth.decorators import login_required
from guestbook.models importGreeting
def list_entries(request):
return object_list(request,Greeting.all())
@login_required
def create_entry(request):
# Add username to POST data, so it gets set in the created model
# You could also use a hidden form field for example, but this is more secure
request.POST = request.POST.copy()
request.POST['author']= str(request.user.key())
return create_object(request,Greeting, post_save_redirect='/guestbook')
并更改/gustbook/urls.py:
from django.conf.urls.defaults import*
urlpatterns = patterns('',
(r'^$','guestbook.views.list_entries'),
(r'^sign/$','guestbook.views.create_entry'),
(r'^signup/$','guestbook.views.create_new_user'),
(r'^login/$','django.contrib.auth.views.login',{'template_name':'guestbook/user_create_form.html'}),
(r'^logout/$','django.contrib.auth.views.logout_then_login',{'login_url':'/guestbook/'}),
)
这个generic view 期望你创建一个/guestbook/templates/greeting_list.html的模板:
<html>
<head>
</head>
<body>
<divclass="login">
{% if user.is_authenticated %}
Welcome, {{ user.username }}
{% if user.is_active %}
<ahref="/guestbook/logout">
{% else %}
<ahref="{% google_logout_url "/guestbook/" %}">
{% endif %}Logout</a>
{% else %}
<ahref="{% google_login_url request.get_full_path %}">Login with your Google account</a><br>
<ahref="/guestbook/login">Login with your normal account</a><br>
<ahref="/guestbook/signup">Sign up</a><br>
{% endif %}
</div>
{% for object in object_list %}
<p>{{object.author.username}}: {{object.content}}</p>
{% endfor %}
<ahref="/guestbook/sign/">Add entry</a>
</body>
</html>
and /guestbook/templates/greeting_form.html:
<inputtype="submit"value="create">
</form>
</body>
</html>
【本文翻译仅为外语学习及阅读目的,原文作者个人观点与译者及译言网无关】