Reputation: 137
I'm trying to get a simple blog running on web.py, it launches fine(python bin/blog.py) but when i enter website it says it cannot find template. I'm pretty sure the path is right, i did a simple todo list before that and it works fine. What's wrong?
here's my project folder look:
-blogpy/
-bin/
-blogwebpy/
-docs/
-templates/
-tests/
Here's the code for blog.py which is located in bin(templates are located in templates):
import web
import model
### Url mappings
urls = (
'/', 'Index',
'/view/(\d+)', 'View',
'/new', 'New',
'/delete/(\d+)', 'Delete',
'/edit/(\d+)', 'Edit',
)
### Templates
t_globals = {
'datestr': web.datestr
}
render = web.template.render('templates/', base='base', globals=t_globals)
class Index:
def GET(self):
""" Show page """
posts = model.get_posts()
return render.index(posts)
class View:
def GET(self, id):
""" View single post """
post = model.get_post(int(id))
return render.view(post)
class New:
form = web.form.Form(
web.form.Textbox('title', web.form.notnull,
size=30,
description="Post title:"),
web.form.Textarea('content', web.form.notnull,
rows=30, cols=80,
description="Post content:"),
web.form.Button('Post entry'),
)
def GET(self):
form = self.form()
return render.new(form)
def POST(self):
form = self.form()
if not form.validates():
return render.new(form)
model.new_post(form.d.title, form.d.content)
raise web.seeother('/')
class Delete:
def POST(self, id):
model.del_post(int(id))
raise web.seeother('/')
class Edit:
def GET(self, id):
post = model.get_post(int(id))
form = New.form()
form.fill(post)
return render.edit(post, form)
def POST(self, id):
form = New.form()
post = model.get_post(int(id))
if not form.validates():
return render.edit(post, form)
model.update_post(int(id), form.d.title, form.d.content)
raise web.seeother('/')
app = web.application(urls, globals())
if __name__ == '__main__':
app.run()
Upvotes: 0
Views: 332
Reputation: 4551
As specified, render
is looking for templates
directory relative to the current working directory, i.e, from where you're trying to execute the program.
A few different ways to fix it:
Execute from blogpy
directory:
python bin/blog.py
This will correctly find templates directory in blogpy/templates
.
Execute from bin
directory, but have render
look in ../templates
. This would require a small change to your code where you specify the location of the templates subdir. (This is what I suggest for your example).
Execute from bin
directory, but move the templates
directory to be under the bin directory. This may look odd, but if you're looking for a simple solution, there's nothing wrong with it.
Use fully specified path names. Ultimately, this is what you should be doing, though it's overkill for your example. You'll save time in the future having a block like:
=== repositories.py ===
import os
_dir_name = os.path.dirname(__file__) or os.getcwd()
templates = os.path.normpath(os.path.join(_dir_name, "../templates"))
You'll be able to locate all your subdirectories (for static content, maybe encryption keys, etc.) reliably regardless how the code is invoked.
Upvotes: 2