webapp2 + jinja2: How can i get uri_for() working in jinja2-views
Question: How can i add pass Model-Specific urls to the Template. Let's say, i want to
build an edit-link. I would guess, using the uri_for() function would be an
easy approach.

But the following gives me "UndefinedError: 'webapp2' is undefined"

    
    
    {% webapp2.uri_for("editGreeting", greeting.key().id()) %}
    

Or should i prepare these in the MainPage-Request-Handler? If so, i don't know
how to add them to each greeting.

The following Code-Example is taken from: <http://webapp-
improved.appspot.com/tutorials/gettingstarted/templates.html>

Controller/Handler

    
    
    class MainPage(webapp2.RequestHandler):
        def get(self):
            guestbook_name=self.request.get('guestbook_name')
            greetings_query = Greeting.all().ancestor(
                guestbook_key(guestbook_name)).order('-date')
            greetings = greetings_query.fetch(10)
    
            if users.get_current_user():
                url = users.create_logout_url(self.request.uri)
                url_linktext = 'Logout'
            else:
                url = users.create_login_url(self.request.uri)
                url_linktext = 'Login'
    
            template_values = {
                'greetings': greetings,
                'url': url,
                'url_linktext': url_linktext,
            }
    
            path = os.path.join(os.path.dirname(__file__), 'index.html')
            self.response.out.write(template.render(path, template_values))
    

Template/View:

    
    
    <html>
      <body>
        {% for greeting in greetings %}
          {% if greeting.author %}
            <b>{{ greeting.author.nickname }}</b> wrote:
          {% else %}
            An anonymous person wrote:
          {% endif %}
          <blockquote>{{ greeting.content|escape }}</blockquote>
        {% endfor %}
    
        <form action="/sign" method="post">
          <div><textarea name="content" rows="3" cols="60"></textarea></div>
          <div><input type="submit" value="Sign Guestbook"></div>
        </form>
    
        <a href="{{ url }}">{{ url_linktext }}</a>
      </body>
    </html
    

The class BaseHandler is the class all handlers inherit from. I tried the
following as @moraes suggested. I still get:

    
    
    value = self.func(obj)
    File "C:\Users\timme04\python\hellowebapp\handlers\basehandler.py", line 23, in jinja2
    return jinja2.get_jinja2(factory=self.jinja2_factory)
    File "C:\Users\timme04\python\hellowebapp\webapp2_extras\jinja2.py", line 212, in get_jinja2
    jinja2 = app.registry[key] = factory(app)
    TypeError: jinja2_factory() takes exactly 1 argument (2 given)
    

:(

    
    
    import webapp2
    
    from webapp2_extras import jinja2
    
    class BaseHandler(webapp2.RequestHandler):
    
        def jinja2_factory(app):
            j = jinja2.Jinja2(app)
            j.environment.filters.update({
                # Set filters.
                # ...
            })
            j.environment.globals.update({
                # Set global variables.
                'uri_for': webapp2.uri_for,
                # ...
            })
            return j
    
        @webapp2.cached_property
        def jinja2(self):
            # Returns a Jinja2 renderer cached in the app registry.
            return jinja2.get_jinja2(factory=self.jinja2_factory)
    
        def render_response(self, _template, **context):
            # Renders a template and writes the result to the response.
            rv = self.jinja2.render_template(_template, **context)
            self.response.write(rv)
    


Answer: You must set `uri_for` as a global variable. One way to do it is to set an
initializer for global variables and filters:

    
    
    import webapp2
    from webapp2_extras import jinja2
    
    def jinja2_factory(app):
        j = jinja2.Jinja2(app)
        j.environment.filters.update({
            # Set filters.
            # ...
        })
        j.environment.globals.update({
            # Set global variables.
            'uri_for': webapp2.uri_for,
            # ...
        })
        return j
    
    class BaseHandler(webapp2.RequestHandler):
    
        @webapp2.cached_property
        def jinja2(self):
            # Returns a Jinja2 renderer cached in the app registry.
            return jinja2.get_jinja2(factory=jinja2_factory)
    
        def render_response(self, _template, **context):
            # Renders a template and writes the result to the response.
            rv = self.jinja2.render_template(_template, **context)
            self.response.write(rv)
    

Edit: changed example to use a RequestHandler.

