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