App 引擎默认 Django 版本更改 [英] App engine default Django version change

查看:31
本文介绍了App 引擎默认 Django 版本更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Since app engine 1.4.2 was released, I am getting warnings like this in my production logs:

您正在使用默认的 Django版本 (0.96).默认的 Django版本将在 App Engine 中更改在不久的将来发布.请调用 use_library() 来显式选择一个 Django 版本.更多信息见http://code.google.com/appengine/docs/python/tools/libraries.html#Django

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 模板的每个处理程序上 - 通过以下方式:

This occurs on every handler where I use a Django template - via the following:

from google.appengine.ext.webapp import template

我想升级到 1.2,但是以下链接似乎不太清楚具体如何执行此操作(或它是否有效):

I'd like to upgrade to 1.2, however the following links don't seem very clear on exactly how to do this (or whether it works at all):

共同点是插入这个:

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

但是,应将其插入到哪个文件中:

However, in what file(s) should this be inserted:

  1. 就在 appengine_config.py 中?
  2. from google.appengine.ext.webapp 导入模板的每个 .py 文件中?
  3. 在项目中的每个 .py 文件中?
  4. 在上面的 1 和(2 或 3)中,还要将 import appengine_config 添加到这些文件中?
  5. 在 3 或 4 中,还围绕内置函数(如 appstats、远程 api、数据存储管理等)添加包装器?
  6. 还有别的吗?
  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() 代码 从这里 在每个导入 django 的处理程序中(直接或通过 google.appengine.ext.webapp.template 甚至只是 django.utils.simplejson):

As described by Nick in the comments of systempuntoout's answer, I inserted this use_library() code from here in every handler that imports django (either directly or via google.appengine.ext.webapp.template or even just django.utils.simplejson):

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

正如 Nick 所建议的,通过首先重构以最小化 app.yaml 引用的处理程序数量(即,更接近 此处描述的场景 1).

As suggested by Nick, this was made easier by first refactoring to minimise the number of handlers referenced by app.yaml (ie, closer to scenario 1 described here).

但是,我已经配置了内置的 appstats,如果我在上传后首先转到/_ah/appstats,那么我会收到此错误:

However, I have the appstats builtin configured, and if I first went to /_ah/appstats after an upload, then I would get this error:

<'google.appengine.dist._library.UnacceptableVersionError'>:django 1.2 被要求,但0.96.4.None 已经在使用中

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

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

I was able to fix this by also including the use_library() code in appengine_config.py.

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

I noticed that by inserting a call to use_library() in appengine_config.py, then it was no longer necessary in all of my handlers. In particular the ones which import google.appengine.ext.webapp.template don't need it, because importing webapp.template loads appengine_config.py. The appstats UI imports webapp.template, which is why this fixed that problem.

但是,我有一些处理程序(例如 json 服务)不会导入 webapp.template,但会导入 django.utils.simplejson.这些处理程序仍然需要直接调用 use_library().否则,如果在新实例上首先调用这些处理程序,则会发生 UnacceptableVersionError.虽然我使用 appengine_config.py 来配置 appstats,这意味着 appengine_config.py 被调用来检测所有请求,但它在页面生命周期中被调用太晚而无法正确配置正确的Django 版本.

However, I had some handlers (eg json services) which don't import webapp.template, but do import django.utils.simplejson. These handlers still require a direct call to use_library(). Otherwise, if those handlers are called first on a new instance, the UnacceptableVersionError occurs. Although I am using appengine_config.py to configure appstats, meaning appengine_config.py gets called to instrument all requests, it gets called too late in the page lifecycle to properly configure the correct version of Django.

一开始这一切似乎都可以正常工作,但后来我发现新的 Django 1.2 和我一直在使用的旧 Django 0.96 之间存在向后不兼容的问题.我的项目结构是这样的:

This all appeared to work okay at first, but then I discovered a backwards incompatibility between the new Django 1.2 and the old Django 0.96 which I'd been using. My project structure is like this:

root
+- admin
|  +- page_admin.html
+- page_base.html

使用 Django 0.96,在 page_admin.html 中使用以下内容可以正常工作:

With Django 0.96, having the following in page_admin.html worked fine:

{% extends "../page_base.html" %}

使用 Django 1.2 时,出现此错误:

With Django 1.2, I got this error:

TemplateDoesNotExist:../page_base.html

TemplateDoesNotExist: ../page_base.html

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

The change in Django 1.2 seems to be that by default, Django doesn't allow loading templates which are above the original template's directory.

此处介绍了一种解决方法a>,但这种方法对我不起作用,因为它要求模板位于模板子目录中.

A workaround for this is described here, but this approach couldn't work for me, as it requires the templates to be in a templates subdirectory.

解决办法是设置一个settings.py文件,将TEMPLATE_DIRS设置为项目根目录,然后修改extends 标记仅引用 "page_base.html",如 所述这里.但是,我在尝试执行此操作时遇到了两个问题.

The solution to this is to set up a settings.py file, set the TEMPLATE_DIRS setting to the project root directory, and then change the extends tag to just reference "page_base.html", as described here. However, I ran into two problems trying to do this.

我使用推荐代码来呈现我的模板,即:

I was using the recommended code to render my template, ie:

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 设置,将其设置为正在渲染的模板的目录.解决这个问题的代码如下:

The first problem is that template.render() overrides the TEMPLATE_DIRS setting, to set it to the directory of the template being rendered. The solution to this is the following code:

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

One downside of this approach though is that template.render() caches the compiled templates, whereas this code doesn't (although that wouldn't be hard to add).

为了配置 TEMPLATE_DIRS 设置,我在我的项目中添加了一个 settings.py:

To configure the TEMPLATE_DIRS setting, I added a settings.py to my project:

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

然后在我的所有处理程序中,在 use_library() 代码之前,我设置了 DJANGO_SETTINGS_MODULE 如此处所述:

And then in all of my handlers, before the use_library() code, I set the DJANGO_SETTINGS_MODULE as described here:

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

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

The second problem was that this didn't work - the settings file wasn't getting loaded, and so the TEMPLATE_DIRS was empty.

Django 设置在第一次访问时从指定的 settings.py 延迟加载.问题是导入 webapp.template 会调用 django.conf.settings.configure() 来尝试设置一些设置.因此,如果在访问任何设置之前导入 webapp.template,则永远不会加载 settings.py(因为设置访问器发现设置已经存在,并且不会尝试加载更多).

Django settings are loaded from the specified settings.py lazily, the first time they are accessed. The problem is that importing webapp.template calls django.conf.settings.configure() to attempt to set up some settings. Therefore if webapp.template is imported before any settings are accessed, then settings.py is never loaded (as the settings accessor finds that settings already exist, and doesn't attempt to load any more).

对此的解决方案是在导入 webapp.template 之前强制访问设置,加载 settings.py.然后,当稍后导入 webapp.template 时,它对 django.conf.settings.configure() 的调用将被忽略.因此,我将所有处理程序(和 appengine_config.py)中的 Django 版本设置代码更改为以下内容:

The solution to this is to force an access to the settings, to load the settings.py, before webapp.template is imported. Then when webapp.template is later imported, its call to django.conf.settings.configure() is ignored. I therefore changed the Django version setup code in all of my handlers (and appengine_config.py) to the following:

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 行代码.

In practise, I actually put all of the above code in a file called setup_django_version.py, and then import that from all of my handlers, rather than duplicating these 6 lines of code everywhere.

然后我更新了我的 page_admin.html 模板以包含这个(即指定 page_base.html 相对于 TEMPLATE_DIRS 设置):>

I then updated my page_admin.html template to include this (ie specify page_base.html relative to the TEMPLATE_DIRS setting):

{% extends "page_base.html" %}

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

And that fixed the problem with rendering the admin page.

这篇关于App 引擎默认 Django 版本更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆