English 中文(简体)
应用程序引擎默认Django版本更改
原标题:App engine default Django version change

自从应用程序引擎1.4.2发布以来,我在生产日志中收到了这样的警告:

You are using the default Django version (0.96). The default Django version will change in an App Engine release in the near future. Please call use_library() to explicitly select a Django version. For more information see http://code.google.com/appengine/docs/python/tools/libraries.html#Django

这发生在我使用Django模板的每个处理程序上——通过以下方式:

from google.appengine.ext.webapp import template

我想升级到1.2,但是以下链接似乎不太清楚如何做到这一点(或者它是否有效):

常见的螺纹是插入以下内容:

from google.appengine.dist import use_library
use_library( django ,  1.2 )

但是,应将其插入到什么文件中:

  1. Just in appengine_config.py?
  2. In every .py file which does from google.appengine.ext.webapp import template?
  3. In every .py file in the project?
  4. In 1 and (2 or 3) above, and also add import appengine_config to those files?
  5. In 3 or 4, and also add wrappers around built-in functions like appstats, remote api, datastore admin, etc?
  6. Something else?

谢谢

最佳回答

正如Nick在systempuntoout答案的评论中所描述的,我插入了use_library()code从这里在每个导入django的处理程序中(直接或通过google.appengine.ext.webapp.template,甚至只是django.utils.simplejson):

from google.appengine.dist import use_library
use_library( django ,  1.2 )

正如Nick所建议的,第一次重构使app.yaml引用的处理程序数量最小化(即更接近此处描述的场景1)。

然而,我已经配置了内置的appstats,如果我在上传后第一次转到/\ah/appstats,那么我会收到以下错误:

< google.appengine.dist._library.UnacceptableVersionError >: django 1.2 was requested, but 0.96.4.None is already in use

我还通过在appengine_config.py中包含use_library()代码来解决这个问题。

我注意到,通过在appengine_config.py中插入对use_library()的调用,在我的所有处理程序中都不再需要它。特别是那些导入google.appengine.ext.webapp.template的应用程序不需要它,因为导入webapp.template会加载appengine_config.py。appstats UI导入webapp.tmplate,这就是解决该问题的原因。

然而,我有一些处理程序(例如json服务),它们不导入webapp.template,而是导入django.utils.simplejson。这些处理程序仍然需要直接调用use_library()。否则,如果在新实例上首先调用这些处理程序,则会出现AcceptableVersionError。尽管我使用appengine_config.py来配置appstats,这意味着调用appngine_connfig.py来处理所有请求,但在页面生命周期中调用它太晚了,无法正确配置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时,我出现了以下错误:

模板Does不存在:/页面基准.html

Django 1.2中的变化似乎是,默认情况下,Django不允许加载原始模板目录之上的模板。

有关此问题的解决方法,请参见此处,但这种方法对我来说不起作用,因为它要求模板位于templates子目录中。

解决方案是设置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设置,将其设置为正在渲染的模板的目录。对此的解决方案是以下代码:

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()缓存编译后的模板,而这段代码则不缓存(尽管这并不难添加)。

为了配置TEMPLATE_DIRS设置,我在项目中添加了设置.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设置是从指定的<code>settings.py</code>中加载的,第一次访问时会延迟加载。问题是导入webapp.template会调用django.conf.settings.config()来尝试设置一些设置。因此,如果在访问任何设置之前导入webapp.template,则永远不会加载settings.py(因为设置访问器发现设置已经存在,并且不再尝试加载)。

解决方案是在导入webapp.template之前,强制访问设置,加载settings.py。然后,当稍后导入webapp.template时,将忽略其对django.conf.settings.config()的调用。因此,我将所有处理程序(以及<code>appengine_config.py</code>)中的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模板,将其包括在内(即相对于template_DIRS设置指定page_base.html

{% extends "page_base.html" %}

这修复了呈现管理页面的问题。

问题回答

从GAE1.5.0开始,有一种更简单的方法可以指定您想要使用的Django模板的哪个版本,尽管暂时没有文档记录。

在<code>appengine_config.py</code>中,包括以下行

webapp_django_version =  1.2 

就是这样。

不再需要use_library()

根据文档如果链接正确,只需在main.py脚本处理程序的开头添加此函数。

有一件事我想提一下,文档并不清楚:如果您使用google.appengine.ext.deferred并在main.py中具有use_library,则当执行延迟任务时,它将不会加载main.py。如果您不幸地将延迟任务作为对实例的第一个请求,它将中止该实例(当main.py在以后的请求中尝试调用use_library时,导致它抛出UnacceptableVersionError)。我认为如果您将use_libary添加到appengine_config.py它也将与递延一起工作,但我们最终切换到常规任务队列(处理程序通过main.py路由)以避免此问题。





相关问题
How to make logging.debug work on Appengine?

I m having a tough time getting the logging on Appengine working. the statement import logging is flagged as an unrecognized import in my PyDev Appengine project. I suspected that this was just an ...

gqlQuery returns object, want list of keys

Is there a way to convert the GqlQuery object to an array of keys, or is there a way to force the query to return an array of keys? For example: items = db.GqlQuery("SELECT __key__ FROM Items") ...

Integrating Google AppEngine with a Thick Client

I want to make a multi-user client-server solution with Java Swing thick client as a front-end and Google AppEngine (Java one) as a back-end. The problem is that GAE provides only web-based forms for ...

sorl.thumbnail : thumbnail is not a valid tag library?

I am trying to install sorl.thumbnail but am getting the following error message: thumbnail is not a valid tag library: Could not load template library from django.templatetags.thumbnail, No module ...