6

I am trying to understand how to create a link to static files in jinja2.

Everything I look up relates to Flask whereas I am using just webapp2 at this stage.

My main.py file looks as follows:

import os
import urllib

from google.appengine.api import users
from google.appengine.ext import ndb

import jinja2
import webapp2

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
    extensions=['jinja2.ext.autoescape'],
    autoescape=True)

class MainPage(webapp2.RequestHandler):
    def get(self): 
    template = JINJA_ENVIRONMENT.get_template('/templates/base.html')  
    self.response.out.write(template.render())

class ConsultsPage(webapp2.RequestHandler):
    def get(self):
    template = JINJA_ENVIRONMENT.get_template('/templates/consults.html')  
    self.response.out.write(template.render())

class CreateConsultPage(webapp2.RequestHandler):
    def get(self):
    template = JINJA_ENVIRONMENT.get_template('/templates/create-consult.html')  
    self.response.out.write(template.render())

app = webapp2.WSGIApplication([
    ('/', MainPage),
    ('/consults', ConsultsPage),
    ('/schedule/create-consult', CreateConsultPage)
], debug=True)

My base.html template contains the links to the static files in "/css", "/js" "/images" etc.

When I look at the localhost:8080/ and localhost:8080/consults all the static files are working. Page looks fine.

However the next level in the structure localhost:8080/consults/create-consult is not linking to static files.

When I view source I see that the css link has rendered as localhost:8080/consults/css/style.css , when the actual location is localhost:8080/css/style.css.

I understand I may need to make all links dynamic via some environment variable called uri_for, but I can't find the correct way to implement this.

I tried to replace my css link with

href="{{ uri_for('static', filename='css/screen.css') }}"

I was told by App Engine uri_for not set.

Basically would like to know the correct process for setting uri_for and then how to incorporate it in the paths for my links to static files.

Any help appreciated.

TimothyAURA
  • 1,329
  • 5
  • 21
  • 44
  • `uri_for()` is a Flask function; it matches the name `static` to a route, which in turn then can be used to generate a path (like `/static/css/screen.css` if the `static` route is configured to handle `/static/` urls). You just need to hardcode the path as `/css/screen.css`, no functions. – Martijn Pieters Feb 06 '17 at 09:59
  • Thanks @martijn-pieters , ok so on closer inspection when I view page source on the localhost:8080/consults/create-consult page that is not rendering any linked static files correctly. What I found is the link in the source is fine, but clicking the link to the css file in the source returns "The url "/consults/css/bootstrap.min.css" does not match any handlers." It seems to want to look for the css in the parent dir of the current dir. So why is it not trying to look for the css folder from the root for this particular page? – TimothyAURA Feb 06 '17 at 10:13
  • OK so I was missing a "/" out front of the path. Hahaha I feel silly, but your response helped -thanks!! – TimothyAURA Feb 06 '17 at 10:53
  • How do I mark your answer as correct? – TimothyAURA Feb 06 '17 at 10:54
  • You can't mark comments, but I created an answer post below with some more information. – Martijn Pieters Feb 06 '17 at 10:57

1 Answers1

11

uri_for() is a Flask-specific function; it matches the name static to a route, which in turn then can be used to generate a path (like /static/css/screen.css if the static route is configured to handle /static/<path:filename> urls).

You just need to hardcode the path as /css/screen.css, no need for functions.

Note the leading /; that makes it an absolute path, relative to your current host. For a page at http://localhost:8080/foo/bar, such a path is then prefixed with http://localhost:8080 to form http://localhost:8080/css/screen.css. When you deploy to the app engine, the hostname will be different.

You could store a prefix URL or path in a global, so you can easily swap out the path for a CDN later:

JINJA_ENVIRONMENT.globals['STATIC_PREFIX'] = '/'

and use that in your templates:

<style src="{{ STATIC_PREFIX }}css/screen.css"></style>

You can now alter all such URLs in one place, by setting the STATIC_PREFIX to a different value, including http://somecdn.cdnprovider.tld/prefix/.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343