Google App Engine、Cloud SQL 和 Django:没有 RDBMS 后端模块
我最近在看一些关于如何设置 google app engine(GAE)和它的云 SQL 以及 django 的教程。总结下来,大部分教程都是让你在本地安装一份 Python 和所有相关的库。有些甚至没有提到,他们假设你会使用本地的 SQL 服务器来进行测试和开发。
首先,你在本地安装的 Python 模块不会自动上传到 GAE。你要么使用 GAE 提供的现有库,要么把所有代码放到项目中再上传。
其次,GAE 会在本地安装所有可用的库,这样你就可以用它们来开发。所以你不应该自己去下载其他的库(这样可能会出现版本冲突或附加问题)。
我设置了一个非常简单的项目。现在还没安装本地的 SQL 服务器。我在用 Windows(真让人抓狂)。我现在想要运行 python manage.py syncdb
。在 settings.py
文件中,DATABASE
必须包含连接信息或网址。根据我的理解,这可以是一个本地数据库(也就是你自己用来开发的,或者在部署后使用的云数据库),可以带有 mysql
的部分,或者设置为从本地连接到云端的 rdbms
(这是什么我也不太清楚)。所以我设置了 'ENGINE': 'google.appengine.ext.django.backends.rdbms'
,结果出现了这个错误:
Error was: No module named google.appengine.ext.django.backends.rdbms.base
我卸载了本地的 django,并设置了我的 PYTHONPATH=C:\Program Files (x86)\Google\google_appengine\lib\django-1.5
。如果不设置这个,我会收到错误,所以我得假设它在使用 GAE 的 django。我还找到了一个路径 C:\Program Files (x86)\Google\google_appengine\google\appengine\ext\django\backends\rdbms
,听起来也很相关。所以我不太确定接下来该怎么做。我猜这个 rdbms
是和 SQL 数据库远程通信所必需的。我希望能够在本地测试,而不是在生产环境中。
我的配置中可能有什么问题导致这个错误呢?
顺便提一下,每当我尝试用 GAE 启动服务器时,我总是会收到 ImportError: Could not import settings 'myblog.settings' (Is it on sys.path?): No module named appengine_toolkit
的错误。python manage.py runserver
运行得很好,直到有请求触发尝试连接 SQL 服务器。
1 个回答
我这里主要缺少的是确保 Python 能够找到 GAE 的库。我在 Linux 上解决了这个问题:
export PYTHONPATH=/usr/local/google_appengine/:/usr/local/google_appengine/lib/:/usr/local/google_appengine/lib/django-1.5/
具体来说,就是:
google_appengine/
google_appengine/lib/
google_appengine/lib/django-1.5/
在 Windows 上,PYTHONPATH
就不管用了。至于出现的错误 Could not import settings 'myblog.settings'
,这个问题只在 Windows 上出现,我也搞不清楚为什么,实在不想浪费时间去研究。
有两件事对我使用 GAE 帮助很大:
- 对 GAE 的 项目结构 有一些基本了解(虽然不是特别明确)。
- 熟悉
virtualenv
(我觉得 这个链接是个不错的入门),并意识到 Google App Engine 的启动器在沙盒和外部库方面是多么混乱。
最后,我的设置是这样的。我使用 virtualenv
将所有包安装到本地的 env
目录。为了在本地测试,这样做很好(配合上面的 PYTHONPATH
)。为了只部署正确的包(比如推送 django-wiki
但不推送 MySQLdb
),我创建了一个 libs
目录,并将我想要的内容在 env/lib/python2.7/site-packages/
中做了符号链接。
作为 PYTHONPATH
的更好替代方案,可以在 settings.py
中使用类似这样的方式:
IS_PRODUCTION = os.getenv('SERVER_SOFTWARE', '').startswith('Google App Engine')
if IS_PRODUCTION:
sys.path.insert(0, 'libs')
else:
sys.path.insert(0, 'env/lib/python2.7/site-packages/')
我还在 app.yaml
中添加了一个 skip_files:
部分,以排除 #- ^env/.*
,并在部署时取消注释。如果我把 env
放在项目目录外面,可能就不需要这样做,正如其他一些人提到的那样。