TemplateDoesNotExist 在 python app-engine django 1.2 上模板渲染相对路径
我在 Windows 计算机上本地运行 1.4.2 appengine SDK。我有一个运行 Django 0.96 的应用程序。模板渲染使用 django 包装器来
google.appengine.ext.webapp.template.render
渲染模板。我经常使用相对路径来链接我的模板,例如
{% extends "../templates/base.html" %}
升级到 Django 1.2 后,find_template 方法从 当使用相对路径时,appengine 的 Django 1.2 lib 文件夹中的 django.template.loader 现在会引发 TemplateDoesNotExist
for loader in template_source_loaders:
try:
#raises TemplateDoesNotExist name='../templates/home.html' dirs=None
source, display_name = loader(name, dirs)
return (source, make_origin(display_name, loader, name, dirs))
except TemplateDoesNotExist:
pass
raise TemplateDoesNotExist(name)
我已经单步执行 Django 和 AppEngine 代码一段时间了,但看不到任何原因。谁能提供更多见解?
谢谢,
理查德
I'm running the 1.4.2 appengine SDK locally on a windows machine. I have an application running Django 0.96. The template rendering is using the django wrapper from
google.appengine.ext.webapp.template.render
to render templates. I often use a relative path to link my templates e.g
{% extends "../templates/base.html" %}
After upgrading to Django 1.2 the find_template method from
django.template.loader in the appengine's Django 1.2 lib folder is now raising a TemplateDoesNotExist when the relative paths are used
for loader in template_source_loaders:
try:
#raises TemplateDoesNotExist name='../templates/home.html' dirs=None
source, display_name = loader(name, dirs)
return (source, make_origin(display_name, loader, name, dirs))
except TemplateDoesNotExist:
pass
raise TemplateDoesNotExist(name)
I've been stepping through the Django and AppEngine code for a while now but can't see any reason for this. Can anyone provide any more insight?
Thanks,
Richard
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当我从 0.96 转换为 1.2 Django 模板时,这个问题也困扰了我。当 SDK 1.4.2 开始发出我需要选择版本的警告时,我最初被迫这样做,但当我研究模板语言中急需的改进时,我渴望做出改变。
然后一切都崩溃了。和您一样,我在
extends
和include
命令中使用了很多相对路径。经过大量的调试和挖掘,但我确实找出了问题的原因并找到了一个很好的解决方案。原因:在 Django 1.2 中,加载模板文件的代码开始使用名为
safe_join
的命令来连接路径部分(您可以在google_appengine\lib\django_1_2\django\template\ 中查看代码) loader\filesystem.py
) 。它不允许相对路径超出它认为的顶级目录。这与 Web 服务器被配置为阻止您仅通过将一些..
粘贴到您的 URL 中来访问服务器的整个文件系统是一样的。最终的结果是,以前很好的方法违反了规则,并且行不通。
我在应用程序中修复此问题的方法是通过实现自定义TemplateLoader,而无需完全重构模板的布局方式。 Django 的模板渲染引擎允许应用程序拥有许多不同的类,这些类知道如何以不同的方式查找模板。如果你查看我上面给出的目录,你会发现提供了几个,它们都是继承自BaseLoader的类。我提供了我自己的模板,它是根据我的模板的布局方式定制的。
我的项目有一个类似 Rails 的布局:
每个模板都扩展
base.html
,有几个模板包含post.html
,并且它们之前使用相对路径来到达其位置在base/
中。理想情况下,我什至不想使用..
up-dir 到达那里,但 0.96 需要它。我创建了以下模板加载器来使用我的方案:并且我通过将应用程序的
main
函数更改为如下所示,使我的自定义模板加载器包含在 Django 尝试的集合中:(然后所有通常进入主函数的其余内容)。
因此,我认为您应该能够修改上面的 TemplateLoader 代码以匹配模板目录的布局方式,它不仅可以让您更好地控制如何布局模板层次结构,还可以更好地控制如何编写 < code>extends 和
include
语句。您不再使用..
,而只是给出相对于项目中的任何内容的模板路径,相当于我的views
目录。This problem bit me too when I converted from 0.96 to 1.2 Django templates. I was initially pushed to do so when SDK 1.4.2 started issuing the warning that I needed to pick a version, but when I looked into the much-needed improvements in the template language, I was eager to make the change.
And then everything broke. Like you, I used a lot of relative paths in my
extends
andinclude
commands. It took a lot of debugging and digging, but I did figure out the cause of the problem and a pretty good solution.The cause: in Django 1.2, the code that loads template files started using a command called
safe_join
to join path parts (you can see the code ingoogle_appengine\lib\django_1_2\django\template\loaders\filesystem.py
) . It won't allow relative paths to go above what it thinks of as the top-level directory. This is the same thing as a web server being configured to prevent you gaining access to the server's whole filesystem just by sticking some..
's into your URL. The end result is that thethat used to be just fine breaks the rules and it isn't going to work.
The way that I fixed this in my application without completely restructuring how my templates are laid out is by implementing a custom TemplateLoader. Django's template rendering engine allows an application to have many different classes that know how to find templates in different ways. If you look in the directory that I gave above, you'll see that there are several provided, and they are all classes that inherit from BaseLoader. I provided my own that is custom-tailored to how my templates are laid out.
My project has a Rails-like lay-out:
Every template extends
base.html
and a couple includepost.html
, and they previously used relative paths to get to their location inbase/
. Ideally, I didn't even want to use the..
up-dir to get there, but it was required with 0.96. I created the following template loader to work with my scheme:And I caused my custom template loader to be included in the collection that Django tries by changing my application's
main
function to look like this:(and then all the rest of the stuff that normally goes into your main function).
So, I think that you should be able to modify the TemplateLoader code above to match how you have your template directories laid out, and it will give you a greater control over not only how you layout you templates hierarcy but also how you write your
extends
andinclude
statement. You no longer use..
but rather just give the path of the template relative to whatever in your project is the equivalent of myviews
directory.收到错误消息 TemplateDoesNotExist: templates\AdminListstr.html 的原因之一
是仔细检查“templates”和模板名称之间使用的斜杠。我浪费了几个小时,然后检查了 os.path.join 返回的值。
总之,您需要确保使用的是“/”而不是Windows“\”。如果您使用了错误的斜杠,您的代码将在 (Windows) 开发中运行,但在部署时会失败。
我的诊断代码打印了这个:看看最后一个斜杠
os.path.join 返回的值为:/base/data/home/apps/s~myapp/1.356037954289984934/templates\LabListstr.html
哎呀呀!
One reason you get the error message TemplateDoesNotExist: templates\AdminListstr.html
Doublecheck the slash you use between "templates" and your template name. I wasted a few hours, then checked the value being returned by os.path.join.
In summary you need to insure you are using "/" not the Windows "\". If you use the wrong slash, your code will work on (Windows) development but fail when deployed.
My diagnostic code printed this: look at the last slash
And the value returned by os.path.join is:/base/data/home/apps/s~myapp/1.356037954289984934/templates\LabListstr.html
Aye yi yi!