【问题标题】:App engine default Django version change应用引擎默认 Django 版本更改
【发布时间】:2011-06-27 01:34:24
【问题描述】:

自发布应用引擎 1.4.2 以来,我在生产日志中收到如下警告:

您正在使用默认的 Django 版本(0.96)。默认的 Django 版本将在 App Engine 中更改 在不久的将来发布。请 调用 use_library() 显式 选择一个 Django 版本。更多 信息见 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. 就在 appengine_config.py 中?
  2. from google.appengine.ext.webapp import template?的每个.py文件中?
  3. 在项目的每个 .py 文件中?
  4. 在上面的 1 和(2 或 3)中,还要在这些文件中添加 import appengine_config
  5. 在 3 或 4 中,是否还围绕内置函数(如 appstats、远程 api、数据存储管理等)添加包装器?
  6. 还有别的吗?

谢谢。

【问题讨论】:

    标签: google-app-engine django-templates


    【解决方案1】:

    正如尼克在 systempuntoout 回答的 cmets 中所述,我在每个导入 django 的处理程序中插入了这个 use_library() 代码 from here(直接或通过 google.appengine.ext.webapp.template 甚至只是 django.utils.simplejson):

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

    正如 Nick 所建议的,通过首先重构以最小化 app.yaml 引用的处理程序的数量(即更接近 scenario 1 described here),这变得更容易了。

    但是,我已经配置了内置的 appstats,如果我在上传后第一次去 /_ah/appstats,那么我会收到这个错误:

    : 要求 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。虽然我使用 appengine_config.py 来配置 appstats,这意味着调用 appengine_config.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,我收到此错误:

    TemplateDoesNotExist: ../page_base.html

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

    here 描述了一种解决方法,但这种方法对我不起作用,因为它要求模板位于模板子目录中。

    解决方法是建立一个settings.py文件,将TEMPLATE_DIRS设置为项目根目录,然后将extends标签改为只引用"page_base.html",为described here。但是,我在尝试这样做时遇到了两个问题。

    我使用recommended code 来渲染我的模板,即:

    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 设置,我在我的项目中添加了settings.py

    PROJECT_ROOT = os.path.dirname(__file__) 
    TEMPLATE_DIRS = (PROJECT_ROOT,)
    

    然后在我所有的处理程序中,在 use_library() 代码之前,我设置了 DJANGO_SETTINGS_MODULE as described here

    import os
    os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' 
    

    第二个问题是这不起作用 - 设置文件没有被加载,因此 TEMPLATE_DIRS 是空的。

    Django 设置从指定的settings.py 延迟加载,第一次访问它们。问题是导入webapp.template 会调用django.conf.settings.configure() 来尝试设置一些设置。因此,如果在访问任何设置之前导入了 webapp.template,则永远不会加载 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 模板以包含这个(即相对于TEMPLATE_DIRS 设置指定page_base.html):

    {% extends "page_base.html" %}
    

    这解决了呈现管理页面的问题。

    【讨论】:

    • +1 感谢您为解决这个问题所做的工作。当我将 Django 版本更改为 1.2 时,我遇到了同样的问题,您为我节省了很多时间。
    • 很棒的答案。回答问题以及所有可能的后续问题。
    • 让我大吃一惊的是,在添加了我的 TEMPLATE_DIRS 变量之后,它似乎仍然不起作用。原来是因为我还在使用自定义应用引擎模板加载器。一旦我切换到 django 的模板加载器,它就开始工作了。
    • 如果 App Engine 文档链接到这个会非常有用。
    • 它需要这么复杂真是太疯狂了。
    【解决方案2】:

    从 GAE 1.5.0 开始,指定要使用哪个版本的 Django 模板的方法要简单得多,尽管暂时没有充分说明。

    appengine_config.py 中,包含该行

    webapp_django_version = '1.2'
    

    就是这样。

    不再需要use_library()

    【讨论】:

    • webapp_django_version这个设置其实在1.5.0之前就已经存在了,但是还是有一些问题。从每个导入 django(目录或间接)的处理程序中,您需要确保首先具有“来自 google.appengine.ext.webapp 导入模板”,否则它将失败。同样在 1.5.0 之前的旧版本中,使用这种技术仍然会出现忽略我提到的 settings.py 的问题。看起来这已经在 1.5.0 中修复了。所以这现在看起来是一种有效的技术,只要你到处导入模板库,这并不难:)
    • 请注意,如果使用 Python 2.7 运行时,这将不起作用。见stackoverflow.com/a/6536723/201828
    【解决方案3】:

    根据您正确链接的documentation,您应该在main.py 脚本处理程序的开头添加此函数。

    【讨论】:

    • @systempuntoout:我没有 main.py 脚本处理程序 - 我的 app.yaml 有大约 20 个处理程序指向不同的 .py 文件,每个处理程序中有大约 1-10 个处理程序类.其中一些使用模板,而另一些则不使用(例如服务和任务)。
    • @Nick:我认为对于是否应该让 app.yaml 指向 N 个带有处理程序的 .py 文件,或者让 app.yaml 指向 1 个 .py 文件,我认为没有具体建议里面有 N 个处理程序?
    • @Saxon 没有,但是通过将其分离到这样的程度,您并没有真正获得任何好处,并且这样做会给自己带来很大的痛苦。
    • @Nick:那么我需要从 app.yaml 调用的每个处理程序中调用 use_library() 吗?在那种情况下,是的,它有点痛苦 :) 否则,到目前为止,它已经很轻松了,并且在保持网站的功能区域分开方面做得很好:) 理论上我可以将它减少到 2(例如,一个用于大多数网站和一个用于login: admin url),但这感觉有点像我在组合不相关的功能。也许大约 4 会是一个更好的折衷方案,例如管理、服务、任务、页面(除了 appstats、远程 api 等内置插件)。
    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-10
      • 1970-01-01
      • 1970-01-01
      • 2018-03-05
      • 2011-08-16
      • 2014-07-18
      相关资源
      最近更新 更多