Изменение версии по умолчанию в движке приложения - PullRequest
49 голосов
/ 14 февраля 2011

С тех пор, как был выпущен механизм приложений 1.4.2, я получаю предупреждения, подобные этому, в моих производственных журналах:

Вы используете Django по умолчанию версия (0,96). Джанго по умолчанию версия изменится в 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. В каждом .py файле, который делает from google.appengine.ext.webapp import template?
  3. В каждом файле .py в проекте?
  4. В 1 и (2 или 3) выше, а также добавить import appengine_config к этим файлам?
  5. В 3 или 4, а также добавить оболочки вокруг встроенных функций, таких как appstats, удаленный API, администратор хранилища данных и т. Д.
  6. Что-то еще?

Спасибо.

Ответы [ 4 ]

56 голосов
/ 17 февраля 2011

Как описано Ником в комментариях к ответу systempuntoout, я вставил этот use_library() код отсюда в каждый обработчик, который импортирует django (напрямую или через google.appengine.ext.webapp.template или даже просто django.utils.simplejson):

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

Как предположил Ник, это было сделано проще благодаря первому рефакторингу, чтобы минимизировать количество обработчиков, на которые ссылается app.yaml (т. Е. Ближе к сценарию 1, описанному здесь ).

Однако у меня настроен встроенный appstats, и если я впервые захожу в / _ah / appstats после загрузки, я получаю эту ошибку:

<'google.appengine.dist._library.UnacceptableVersionError '>: запрошен django 1.2, но 0.96.4. Ни один из них не используется

Мне удалось это исправить, также добавив код use_library() в appengine_config.py.

Я заметил, что, вставляя вызов в use_library() в appengine_config.py, он больше не нужен во всех моих обработчиках.В частности, те, которые импортируют google.appengine.ext.webapp.template, не нуждаются в этом, потому что импорт webapp.template загружает appengine_config.py.Пользовательский интерфейс appstats импортирует webapp.template, поэтому это решило эту проблему.

Однако у меня были некоторые обработчики (например, службы json), которые не импортируют webapp.template, но импортируют django.utils.simplejson.Этим обработчикам по-прежнему требуется прямой вызов use_library().В противном случае, если эти обработчики вызываются первыми в новом экземпляре, происходит UnacceptableVersionError.Хотя я использую appengine_config.py для настройки приложений, то есть 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 не позволяет загружать шаблоны, которые находятся над каталогом исходного шаблона.

Обходной путь для этого описан здесь , но этот подход не может работать для меня, поскольку он требует, чтобы шаблоны находились в подкаталоге шаблонов.

Решением этой проблемы является установка файла 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, я добавил 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 никогда не загружается (так как средство доступа к настройкам обнаруживает, что настройки уже существуют, и больше не пытается загрузить).

Решением этой проблемы является принудительный доступ к настройкам для загрузки settings.py до импорта webapp.template. Затем, когда webapp.template импортируется позже, его вызов django.conf.settings.configure() игнорируется. Поэтому я изменил код установки версии Django во всех моих обработчиках (и appengine_config.py) следующим образом:

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" %}

И это исправило проблему с отображением страницы администратора.

17 голосов
/ 09 июня 2011

Начиная с GAE 1.5.0, существует гораздо более простой, хотя и недокументированный, способ указать, какую версию шаблонов Django вы хотите использовать.

В appengine_config.py включить строку

webapp_django_version = '1.2'

Вот и все.

Больше не нужно use_library().

3 голосов
/ 14 февраля 2011

Согласно документации , которую вы правильно связываете, вам нужно просто добавить эту функцию в начале обработчика сценария main.py.

2 голосов
/ 05 июня 2013

Я хотел бы отметить, что документация не дает ясности: если вы используете google.appengine.ext.deferred и в вашем main.py есть use_library, то если отложенная задача выполнена , она НЕ будет загружать main.py, и если вам не повезло, что отложенная задача является вашим первым запросом к экземпляру, она будет блокировать экземпляр (вызывая выброс * 1011). * когда ваш main.py пытается позвонить use_library по более позднему запросу). Я думаю, что если вы добавите use_libary к appengine_config.py, это будет работать и с deferred, но мы закончили тем, что переключились на обычные очереди задач (которые обрабатываются через main.py), чтобы избежать этого проблема.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...