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

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

问题描述

由于应用程序引擎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. 在google.appengine.ext.webapp导入模板中的每个.py文件中都有

  3. 在项目的每个.py文件中?

  4. 在上面的1和(2或3)中,并添加 import appengine_config 到这些文件?

  5. 在3或4中,还可以在appstats,远程api,datastore admin等内置函数中添加包装器?


谢谢。

解决方案

如尼克在systempuntoout的回答的评论中所述,我插入了这个 use_library()代码 google.appengine)中的com / appengine / docs / python / tools / libraries.html#Djangorel =nofollow noreferrer>从这里或甚至只是 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被请求,但
0.96.4.None已被使用


我可以通过在 appengine_config.py use_library()代码来解决这个问题$ c $。

我注意到通过在中插入一个调用 use_library() appengine_config.py ,那么在我的所有处理程序中不再需要它。特别是导入 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不会允许加载原始模板目录之上的模板。



解决方法是描述这里,但是这种方法对我来说无法工作,因为它需要模板在一个templates子目录中。 / p>

解决方案是设置一个 settings.py 文件,设置 TEMPLATE_DIRS 设置到项目ro ot目录,然后将 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 设置,我添加了一个 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 是空的。 p>

Django设置从第一次被访问时从指定的 settings.py 加载。问题是导入 webapp.template 调用 django.conf.settings.configure()来尝试设置一些设置。因此,如果在访问任何设置之前导入了 webapp.template ,则从未加载 settings.py 访问者发现设置已经存在,并且不再尝试加载)。



解决方案是强制访问设置,加载 settings.py ,之前 webapp.template 被导入。然后当 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 ):

  {%extendspage_base.html%} 

这样可以解决渲染管理页面的问题。


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

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

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

from google.appengine.ext.webapp import template

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):

The common thread is to insert this:

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

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

  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?

Thanks.

解决方案

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')

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).

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 was requested, but 0.96.4.None is already in use

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

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.

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.

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

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

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

With Django 1.2, I got this error:

TemplateDoesNotExist: ../page_base.html

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 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.

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))

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))) 

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).

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

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

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' 

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 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).

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

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.

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天全站免登陆