应用引擎默认的Django版本更改
由于应用程序引擎1.4.2发布,我在我的生产日志中得到这样的警告:
您正在使用默认的Django版本(0.96)。 在不久的将来,默认的Django版本将在App Engine版本中发生变化。 请调用use_library()来显式select一个Django版本。 有关详情,请参阅http://code.google.com/appengine/docs/python/tools/libraries.html#Django
这发生在我使用Django模板的每个处理程序上 – 通过以下方式:
from google.appengine.ext.webapp import template
我想升级到1.2,但是下面的链接到底是怎么做的(或者它是否工作)似乎并不是很清楚:
- http://code.google.com/appengine/docs/python/tools/libraries.html#Django
- http://code.google.com/p/googleappengine/issues/detail?id=1758
- http://code.google.com/p/googleappengine/issues/detail?id=4489
- http://www.mediacrafters.org/post/django11-on-appengine
共同的线索是插入这个:
from google.appengine.dist import use_library use_library('django', '1.2')
但是,应该在什么文件中插入:
- 只是在appengine_config.py?
- 在
from google.appengine.ext.webapp import template
每个.py文件中? - 在项目中的每个.py文件中?
- 在上面的1和(2或3)中,还将
import appengine_config
添加到这些文件中? - 在3或4,还添加了内置函数,如appstats,远程API,数据存储pipe理员等的包装?
- 别的东西?
谢谢。
正如在systempuntoout的回答中,Nick所描述的那样,我从这里插入了这个use_library()
代码到每个导入django的处理程序(直接或通过google.appengine.ext.webapp.template
或者甚至只是django.utils.simplejson
)中:
from google.appengine.dist import use_library use_library('django', '1.2')
正如Nick所build议的那样,通过第一次重构,使得app.yaml所引用的处理程序的数量最小化(即,更接近这里描述的场景1 ),这变得更容易。
不过,我已经configuration了内置的appstats,如果我在上传之后首先去了/ _ah / appstats,那么我会得到这个错误:
<'google.appengine.dist._library.UnacceptableVersionError'>:请求了django 1.2,但0.96.4.None已经在使用
我可以通过在appengine_config.py
包含use_library()
代码来解决这个问题。
我注意到,通过在appengine_config.py
插入对use_library()
的调用,那么在我的所有处理程序中就不再需要它了。 尤其是那些导入google.appengine.ext.webapp.template
不需要它,因为导入webapp.template
加载appengine_config.py
。 appstats UI导入webapp.template
,这就是为什么这个问题得到解决。
不过,我有一些处理程序(例如json服务)不会导入webapp.template
,但是会导入django.utils.simplejson
。 这些处理程序仍然需要直接调用use_library()
。 否则,如果在新实例上首先调用这些处理程序,则会发生UnacceptableVersionError
。 尽pipe我使用appengine_config.py
来configurationappstats,但是appengine_config.py
被调用来处理所有的请求,在页面生命周期中被调用得太晚,无法正确configuration正确版本的Django。
这一切似乎开始工作起来,但后来我发现了新的Django 1.2和我曾经使用的旧的Django 0.96之间的向后不兼容。 我的项目结构是这样的:
root +- admin | +- page_admin.html +- page_base.html
使用Django 0.96,在page_admin.html中有以下工作正常:
{% extends "../page_base.html" %}
用Django 1.2,我得到这个错误:
TemplateDoesNotExist:../page_base.html
Django 1.2中的变化似乎是,默认情况下,Django不允许加载模板的原始模板的目录之上。
这里描述了一个解决方法,但是这种方法对我不起作用,因为它要求模板在模板子目录中。
解决方法是设置settings.py
文件,将TEMPLATE_DIRS
设置为项目根目录,然后将extends
标记更改为仅引用"page_base.html"
,如此处所述 。 但是,我遇到了两个问题,试图做到这一点。
我正在使用推荐的代码来呈现我的模板,即:
template_values = { ... } path = os.path.join(os.path.dirname(__file__), 'page_admin.html') self.response.out.write(template.render(path, template_values))
第一个问题是, template.render()
会覆盖TEMPLATE_DIRS
设置,将其设置为要呈现的模板的目录。 对此的解决scheme是以下代码:
template_values = { ... } path = os.path.join(os.path.dirname(__file__), 'page_admin.html') template_file = open(path) compiled_template = template.Template(template_file.read()) template_file.close() self.response.out.write(compiled_template.render(template.Context(template_values)))
这种方法的一个缺点是template.render()
caching了编译好的模板,而这段代码却没有(尽pipe这样做不难)。
要configurationTEMPLATE_DIRS
设置,我添加了一个settings.py
到我的项目中:
PROJECT_ROOT = os.path.dirname(__file__) TEMPLATE_DIRS = (PROJECT_ROOT,)
然后在我的所有处理程序中,在use_library()
代码之前,我设置了DJANGO_SETTINGS_MODULE
如下所述 :
import os os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
第二个问题是,这不起作用 – 设置文件没有得到加载,所以TEMPLATE_DIRS
是空的。
Django设置是从指定的settings.py
中第一次被访问时被加载的。 问题是导入webapp.template
调用django.conf.settings.configure()
尝试设置一些设置。 因此,如果在访问任何设置之前导入了webapp.template
,那么settings.py
永远不会被加载(因为设置访问器发现设置已经存在,并且不会再尝试加载)。
解决scheme是强制访问settings.py
,在导入webapp.template
之前加载settings.py
。 然后,当稍后导入webapp.template
时,将忽略其对django.conf.settings.configure()
调用。 因此,我将所有处理程序(和appengine_config.py
)中的Django版本设置代码更改为以下内容:
import os os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' from google.appengine.dist import use_library use_library('django', '1.2') from django.conf import settings _ = settings.TEMPLATE_DIRS
实际上,我将所有上面的代码放在一个名为setup_django_version.py
的文件中,然后从我的所有处理程序中导入,而不是在任何地方复制这6行代码。
然后,我更新了我的page_admin.html
模板以包含此(即指定page_base.html
相对于TEMPLATE_DIRS
设置):
{% extends "page_base.html" %}
这解决了渲染pipe理页面的问题。
从GAE 1.5.0开始,有很多简单的,虽然暂时没有详细logging的方法,可以指定要使用的Django模板的版本。
在appengine_config.py
,包含该行
webapp_django_version = '1.2'
而已。
不再需要use_library()
。
根据您正确链接的文档 ,您应该在main.py
脚本处理程序的开头添加此函数。
有一件事我想提到, 文档没有明确说明:如果你使用google.appengine.ext.deferred
并且在你的main.py
有main.py
,那么当执行延迟任务时,它不会加载main.py
如果你不幸有一个推迟的任务作为你对实例的第一个请求,那么它就会执行这个实例(当你的main.py
试图在稍后的请求中调用use_library
时,它会抛出UnacceptableVersionError
)。 我想如果你添加use_libary
到appengine_config.py
它也可以和deferred
工作,但是我们最终切换到了常规任务队列(通过main.py
路由的处理程序)以避免这个问题。