Как описано Ником в комментариях к ответу 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" %}
И это исправило проблему с отображением страницы администратора.