watsonpy / watson-framework

A Python 3 web app framework.
BSD 3-Clause "New" or "Revised" License
104 stars 12 forks source link

Template lookup not working on Windows: Exception Type:jinja2.exceptions.TemplateNotFound #6

Closed moigagoo closed 10 years ago

moigagoo commented 10 years ago

Hi,

After starting a dev server and accessing http://127.0.0.1:8000 I get this error:

Exception Type:jinja2.exceptions.TemplateNotFound Exception Message:index\get.html

(Full screenshot http://i.imgur.com/Lb8Rt1f.png)

The template is obviously there since I'm just using unmodified default project and app.

I'm trying to locate the issue: is that a Jinja2's or Watson's? Looks awfully like POSIX slashes are hardcoded somewhere or abspath is missing, but I can't be sure.

Any thoughts?

Thanks!

simoncoulton commented 10 years ago

Thanks for reporting the bug!

I haven't actually tested it on Windows yet, but there's no paths hardcoded in there (line 76-94) in framework.listeners. The basic logic behind it is get the controller and method called and generate the path based off that (e.g controller Index and method GET returns a list ['index', 'get'], which is then sent to os.path.join(), which depending on your OS would output index\get or index/get and then appends the format onto the end). Jinja2 is then responsible for determining the location of that template based on the supplied environment paths.

Could you try overriding the view configuration in your application config to include os.path.abspath and let me know if that works?

    views = {
        'renderers': {
            'jinja2': {
                'config': {
                    'paths': [os.path.abspath(os.path.join(os.getcwd(), 'views'))],
moigagoo commented 10 years ago

Sure, I'll try playing with the config.

There's an interesting thing I've found.

In Jinja2 loaders.py there's a method load of the ChoiceLoader class.

The name param it receives has proper Windows slashes, which means that os.path.join has been applied earlier and it worked OK.

The funny thing is that Jinja2 doesn't really care about it :-) It accepts POSIX slash paths anyway.

So, if I just replace \ with /, the code will work OK: name = name.replace('\\', '/')

The point is, you should feed Jinja with POSIX paths with no regard for the current OS.

moigagoo commented 10 years ago

Changing the config did not help.

As I said, the problem is that you feed Jinja with prepared paths, whereas it expects simple POSIX paths and converts them itself.

I guess, you should think of the name param not as of an OS path to the template file, but rather a standardized location of the template object; so it's a higher abstraction level.

simoncoulton commented 10 years ago

If that's the case, some modifications can be made to the renderer to specifically convert all paths accordingly prior to calling template.render(). The main reason nothing is done prior to it hitting the Jinja2 renderer is that the user may switch out Jinja2 for their preferred templating library.

I'll add this to the list of fixes for the next version. If you'd like to patch it yourself in the interim on your machine, modify the following code: https://github.com/watsonpy/watson-framework/blob/master/watson/framework/views/renderers/jinja2.py#L312-316 :)

moigagoo commented 10 years ago

I've removed a silly comment. Thanks for the help!