Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

static_url_filter #24

Closed
wants to merge 4 commits into from

3 participants

@kschuetz

I think it would be useful for pyramid_jinja2 to provide a static_url filter in addition to its route_url and model_url filters. I've added it in these commits, as well as updated the tests and docs.

Regards,
Kevin

@sontek

+1 on this, anything holding back the commit?

@mcdonc
Owner

Fixed via pull #31.

@mcdonc mcdonc closed this
@kschuetz

What was different in #31 vs. this one?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
595 docs/index.rst
@@ -1,295 +1,300 @@
-==============
-pyramid_jinja2
-==============
-
-Overview
-========
-
-:term:`pyramid_jinja2` is a set of bindings that make templates written for the
-:term:`Jinja2` templating system work under the :term:`Pyramid` web framework.
-
-Installation
-============
-
-Install using setuptools, e.g. (within a virtualenv)::
-
- $ easy_install pyramid_jinja2
-
-Setup
-=====
-
-There are two ways to make sure that ``pyramid_jinja2`` is active. Both
-are completely equivalent:
-
-#) Use the ``includeme`` function via ``config.include``::
-
- config.include('pyramid_jinja2')
-
-#) Ensure that some ZCML file with an analogue of the following
- contents is executed by your Pyramid application::
-
- <include package="pyramid_jinja2"/>
-
-Once activated either of these says, the following happens:
-
-#) Files with the ``.jinja2`` extension are considered to be
- :term:`Jinja2` templates.
-
-#) The :func:`pyramid_jinja2.add_jinja2_search_path` directive is added to
- the :term:`configurator` instance.
-
-#) The :func:`pyramid_jinja2.add_jinja2_extension` directive is added to the
- :term:`configurator` instance.
-
-#) The :func:`pyramid_jinja2.get_jinja2_environment` directive is added to the
- :term:`configurator` instance.
-
-To setup the jinja2 search path either one of the following steps must be taken:
-
-#) Add ``jinja2.directories`` to your ``.ini`` settings file using the pyramid
- asset spec::
-
- jinja2.directories = yourapp:templates
-
-#) Or Alternatively by using the ``add_jinja2_search_path`` directive attached
- to your application's :term:`configurator` instance also using the pyramid asset
- spec::
-
- config.add_jinja2_search_path("yourapp:templates")
-
-.. warning::
-
- If you do not explicitly configure your jinja2 search path it will default to
- the root of your application. If configured in this way all subsequent paths
- will need to be specified relative to the root of your application's package.
- For example:
-
- Without the search path configured:
-
- .. code-block:: text
-
- @view_config(renderer='templates/mytemplate.jinja2')
-
- With the search path configured:
-
- .. code-block:: text
-
- @view_config(renderer='mytemplate.jinja2')
-
-Usage
-=====
-
-Once :term:`pyramid_jinja2` been activated ``.jinja2`` templates
-can be loaded either by looking up names that would be found on
-the :term:`Jinja2` search path or by looking up asset specifications.
-
-Template Lookups
-----------------
-
-The default lookup mechanism for templates uses the :term:`Jinja2`
-search path. (specified with ``jinja2.directories`` or by using the
-add_jinja2_search_path directive on the :term:`configurator` instance.)
-
-Rendering :term:`Jinja2` templates with a view like this is typically
-done as follows (where the ``templates`` directory is expected to
-live in the search path):
-
-.. code-block:: python
- :linenos:
-
- from pyramid.view import view_config
-
- @view_config(renderer='mytemplate.jinja2')
- def myview(request):
- return {'foo':1, 'bar':2}
-
-Rendering templates outside of a view (and without a request) can be
-done using the renderer api:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.renderers import render_to_response
- render_to_response('mytemplate.jinja2', {'foo':1, 'bar':2})
-
-:term:`Template Inheritance`
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-:term:`Template inheritance` can use asset specs in the same manner as regular
-template lookups. An example:
-
-.. code-block:: html+django
- :linenos:
-
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
- <!-- templates/layout.jinja2 -->
-
- <html lang="en">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <link rel="stylesheet" href="style.css" />
- </head>
- <body>
- <div id="content">{% block content %}{% endblock %}</div>
- </body>
-
-.. code-block:: html+django
- :linenos:
-
- <!-- templates/root.jinja2 -->
- {% extends "templates/layout.jinja2" %}
- {% block content %}
- <h1>Yes</h1>
- <p>
- Some random paragraph.
- </p>
- {% endblock %}
-
-For further information on :term:`template inheritance` in Jinja2
-templates please see http://jinja.pocoo.org/docs/templates/#template-inheritance.
-
-Asset Specification Lookups
----------------------------
-
-Looking up templates via asset specification is a feature specific
-to :term:`Pyramid`. For further info please see `Understanding
-Asset Specifications
-<http://docs.pylonsproject.org/projects/pyramid/1.0/narr/assets.html#understanding-asset-specifications>`_.
-Overriding templates in this style uses the standard
-`pyramid asset overriding technique
-<http://docs.pylonsproject.org/projects/pyramid/1.0/narr/assets.html#overriding-assets>`_.
-
-Settings
-========
-
-Jinja2 derives additional settings to configure its template renderer. Many
-of these settings are optional and only need to be set if they should be
-different from the default. The below values can be present in the ``.ini``
-file used to configure the Pyramid application (in the ``app`` section
-representing your Pyramid app) or they can be passed directly within the
-``settings`` argument passed to a Pyramid Configurator.
-
-reload_templates
-
- ``true`` or ``false`` representing whether Jinja2 templates should be
- reloaded when they change on disk. Useful for development to be ``true``.
-
-jinja2.directories
-
- A list of directory names or a newline-delimited string with each line
- representing a directory name. These locations are where Jinja2 will
- search for templates. Each can optionally be an absolute resource
- specification (e.g. ``package:subdirectory/``).
-
-jinja2.input_encoding
-
- The input encoding of templates. Defaults to ``utf-8``.
-
-jinja2.autoescape
-
- ``true`` or ``false`` representing whether Jinja2 will autoescape rendered
- blocks.
-
-jinja2.extensions
-
- A list of extension objects or a newline-delimited set of dotted import
- locations where each line represents an extension.
-
-jinja2.filters
-
- A dictionary mapping filter name to filter object, or a newline-delimted
- string with each line in the format ``name = dotted.name.to.filter``
- representing Jinja2 filters.
-
-
-Jinja2 Filters
-==============
-
-``pyramid_jinja2`` provides two filters.
-
-
-.. currentmodule:: pyramid_jinja2.filters
-.. autofunction:: model_url_filter
-.. autofunction:: route_url_filter
-
-To use these filters, configure the settings of ``jinja2.filters``:
-
-.. code-block:: ini
- :linenos:
-
- [app:yourapp]
- # ... other stuff ...
- jinja2.filters =
- model_url = pyramid_jinja2.filters:model_url_filter
- route_url = pyramid_jinja2.filters:route_url_filter
-
-And use the filters in template.
-
-.. code-block:: html
-
- <a href="{{context|model_url('edit')}}">Edit</a>
-
- <a href="{{'top'|route_url}}">Top</a>
-
-Creating a Jinja2 ``Pyramid`` Project
-=====================================
-
-After you've got ``pyramid_jinja2`` installed, you can invoke the following
-command to create a Jinja2-based Pyramid project::
-
- $ paster create -t pyramid_jinja2_starter
-
-This is a good way to see a working Pyramid application that uses Jinja2, even
-if you wind up not using the result.
-
-.. code-block:: text
- :linenos:
-
- # make sure Babel is installed
- easy_install Babel
-
- # extract translatable strings from *.jinja2 / *.py
- python setup.py extract_messages
- python setup.py update_catalog
-
- # Translate strings in <mypackage>/locale/<mylocale>/LC_MESSAGES/<myproject>.po
- # and re-compile *.po files
- python setup.py compile_catalog
-
-
-Paster Template I18N
---------------------
-
-The paster template automatically sets up pot/po/mo locale files for use
-with the generated project.
-
-The usual pattern for working with i18n in pyramid_jinja2 is as follows:
-
-
-
-
-More Information
-================
-
-.. toctree::
- :maxdepth: 1
-
- i18n.rst
- glossary.rst
- api.rst
-
-Reporting Bugs / Development Versions
-=====================================
-
-Visit http://github.com/Pylons/pyramid_jinja2 to download development or tagged
-versions.
-
-Visit http://github.com/Pylons/pyramid_jinja2/issues to report bugs.
-
-Indices and tables
-------------------
-
-* :ref:`glossary`
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
+==============
+pyramid_jinja2
+==============
+
+Overview
+========
+
+:term:`pyramid_jinja2` is a set of bindings that make templates written for the
+:term:`Jinja2` templating system work under the :term:`Pyramid` web framework.
+
+Installation
+============
+
+Install using setuptools, e.g. (within a virtualenv)::
+
+ $ easy_install pyramid_jinja2
+
+Setup
+=====
+
+There are two ways to make sure that ``pyramid_jinja2`` is active. Both
+are completely equivalent:
+
+#) Use the ``includeme`` function via ``config.include``::
+
+ config.include('pyramid_jinja2')
+
+#) Ensure that some ZCML file with an analogue of the following
+ contents is executed by your Pyramid application::
+
+ <include package="pyramid_jinja2"/>
+
+Once activated either of these says, the following happens:
+
+#) Files with the ``.jinja2`` extension are considered to be
+ :term:`Jinja2` templates.
+
+#) The :func:`pyramid_jinja2.add_jinja2_search_path` directive is added to
+ the :term:`configurator` instance.
+
+#) The :func:`pyramid_jinja2.add_jinja2_extension` directive is added to the
+ :term:`configurator` instance.
+
+#) The :func:`pyramid_jinja2.get_jinja2_environment` directive is added to the
+ :term:`configurator` instance.
+
+To setup the jinja2 search path either one of the following steps must be taken:
+
+#) Add ``jinja2.directories`` to your ``.ini`` settings file using the pyramid
+ asset spec::
+
+ jinja2.directories = yourapp:templates
+
+#) Or Alternatively by using the ``add_jinja2_search_path`` directive attached
+ to your application's :term:`configurator` instance also using the pyramid asset
+ spec::
+
+ config.add_jinja2_search_path("yourapp:templates")
+
+.. warning::
+
+ If you do not explicitly configure your jinja2 search path it will default to
+ the root of your application. If configured in this way all subsequent paths
+ will need to be specified relative to the root of your application's package.
+ For example:
+
+ Without the search path configured:
+
+ .. code-block:: text
+
+ @view_config(renderer='templates/mytemplate.jinja2')
+
+ With the search path configured:
+
+ .. code-block:: text
+
+ @view_config(renderer='mytemplate.jinja2')
+
+Usage
+=====
+
+Once :term:`pyramid_jinja2` been activated ``.jinja2`` templates
+can be loaded either by looking up names that would be found on
+the :term:`Jinja2` search path or by looking up asset specifications.
+
+Template Lookups
+----------------
+
+The default lookup mechanism for templates uses the :term:`Jinja2`
+search path. (specified with ``jinja2.directories`` or by using the
+add_jinja2_search_path directive on the :term:`configurator` instance.)
+
+Rendering :term:`Jinja2` templates with a view like this is typically
+done as follows (where the ``templates`` directory is expected to
+live in the search path):
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.view import view_config
+
+ @view_config(renderer='mytemplate.jinja2')
+ def myview(request):
+ return {'foo':1, 'bar':2}
+
+Rendering templates outside of a view (and without a request) can be
+done using the renderer api:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.renderers import render_to_response
+ render_to_response('mytemplate.jinja2', {'foo':1, 'bar':2})
+
+:term:`Template Inheritance`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+:term:`Template inheritance` can use asset specs in the same manner as regular
+template lookups. An example:
+
+.. code-block:: html+django
+ :linenos:
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+ <!-- templates/layout.jinja2 -->
+
+ <html lang="en">
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <link rel="stylesheet" href="style.css" />
+ </head>
+ <body>
+ <div id="content">{% block content %}{% endblock %}</div>
+ </body>
+
+.. code-block:: html+django
+ :linenos:
+
+ <!-- templates/root.jinja2 -->
+ {% extends "templates/layout.jinja2" %}
+ {% block content %}
+ <h1>Yes</h1>
+ <p>
+ Some random paragraph.
+ </p>
+ {% endblock %}
+
+For further information on :term:`template inheritance` in Jinja2
+templates please see http://jinja.pocoo.org/docs/templates/#template-inheritance.
+
+Asset Specification Lookups
+---------------------------
+
+Looking up templates via asset specification is a feature specific
+to :term:`Pyramid`. For further info please see `Understanding
+Asset Specifications
+<http://docs.pylonsproject.org/projects/pyramid/1.0/narr/assets.html#understanding-asset-specifications>`_.
+Overriding templates in this style uses the standard
+`pyramid asset overriding technique
+<http://docs.pylonsproject.org/projects/pyramid/1.0/narr/assets.html#overriding-assets>`_.
+
+Settings
+========
+
+Jinja2 derives additional settings to configure its template renderer. Many
+of these settings are optional and only need to be set if they should be
+different from the default. The below values can be present in the ``.ini``
+file used to configure the Pyramid application (in the ``app`` section
+representing your Pyramid app) or they can be passed directly within the
+``settings`` argument passed to a Pyramid Configurator.
+
+reload_templates
+
+ ``true`` or ``false`` representing whether Jinja2 templates should be
+ reloaded when they change on disk. Useful for development to be ``true``.
+
+jinja2.directories
+
+ A list of directory names or a newline-delimited string with each line
+ representing a directory name. These locations are where Jinja2 will
+ search for templates. Each can optionally be an absolute resource
+ specification (e.g. ``package:subdirectory/``).
+
+jinja2.input_encoding
+
+ The input encoding of templates. Defaults to ``utf-8``.
+
+jinja2.autoescape
+
+ ``true`` or ``false`` representing whether Jinja2 will autoescape rendered
+ blocks.
+
+jinja2.extensions
+
+ A list of extension objects or a newline-delimited set of dotted import
+ locations where each line represents an extension.
+
+jinja2.filters
+
+ A dictionary mapping filter name to filter object, or a newline-delimted
+ string with each line in the format ``name = dotted.name.to.filter``
+ representing Jinja2 filters.
+
+
+Jinja2 Filters
+==============
+
+``pyramid_jinja2`` provides three filters.
+
+
+.. currentmodule:: pyramid_jinja2.filters
+.. autofunction:: model_url_filter
+.. autofunction:: route_url_filter
+.. autofunction:: static_url_filter
+
+To use these filters, configure the settings of ``jinja2.filters``:
+
+.. code-block:: ini
+ :linenos:
+
+ [app:yourapp]
+ # ... other stuff ...
+ jinja2.filters =
+ model_url = pyramid_jinja2.filters:model_url_filter
+ route_url = pyramid_jinja2.filters:route_url_filter
+ static_url = pyramid_jinja2.filters:static_url_filter
+
+And use the filters in template.
+
+.. code-block:: html
+
+ <a href="{{context|model_url('edit')}}">Edit</a>
+
+ <a href="{{'top'|route_url}}">Top</a>
+
+ <link rel="stylesheet" href="{{'yourapp:static/css/style.css'|static_url}}" />
+
+
+Creating a Jinja2 ``Pyramid`` Project
+=====================================
+
+After you've got ``pyramid_jinja2`` installed, you can invoke the following
+command to create a Jinja2-based Pyramid project::
+
+ $ paster create -t pyramid_jinja2_starter
+
+This is a good way to see a working Pyramid application that uses Jinja2, even
+if you wind up not using the result.
+
+.. code-block:: text
+ :linenos:
+
+ # make sure Babel is installed
+ easy_install Babel
+
+ # extract translatable strings from *.jinja2 / *.py
+ python setup.py extract_messages
+ python setup.py update_catalog
+
+ # Translate strings in <mypackage>/locale/<mylocale>/LC_MESSAGES/<myproject>.po
+ # and re-compile *.po files
+ python setup.py compile_catalog
+
+
+Paster Template I18N
+--------------------
+
+The paster template automatically sets up pot/po/mo locale files for use
+with the generated project.
+
+The usual pattern for working with i18n in pyramid_jinja2 is as follows:
+
+
+
+
+More Information
+================
+
+.. toctree::
+ :maxdepth: 1
+
+ i18n.rst
+ glossary.rst
+ api.rst
+
+Reporting Bugs / Development Versions
+=====================================
+
+Visit http://github.com/Pylons/pyramid_jinja2 to download development or tagged
+versions.
+
+Visit http://github.com/Pylons/pyramid_jinja2/issues to report bugs.
+
+Indices and tables
+------------------
+
+* :ref:`glossary`
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
View
15 pyramid_jinja2/filters.py
@@ -1,15 +1,16 @@
-from pyramid.url import resource_url, route_url
+from pyramid.url import resource_url, route_url, static_url
from pyramid.threadlocal import get_current_request
__all__ = [
'model_url_filter',
'route_url_filter',
+ 'static_url_filter',
]
def model_url_filter(model, *elements, **kw):
"""A filter from ``model`` to a string representing the absolute URL.
- this filter call `pyramid.url.resource_url`.
+ This filter calls `pyramid.url.resource_url`.
"""
request = get_current_request()
return resource_url(model, request, *elements, **kw)
@@ -17,7 +18,15 @@ def model_url_filter(model, *elements, **kw):
def route_url_filter(route_name, *elements, **kw):
"""A filter from ``route_name`` to a string representing the absolute URL.
- this filter call `pyramid.url.route_url`.
+ This filter calls `pyramid.url.route_url`.
"""
request = get_current_request()
return route_url(route_name, request, *elements, **kw)
+
+
+def static_url_filter(path, **kw):
+ """A filter from ``path`` to a string representing the absolute URL.
+ This filter calls `pyramid.url.static_url`.
+ """
+ request = get_current_request()
+ return static_url(path, request, **kw)
View
157 pyramid_jinja2/tests/test_filters.py
@@ -1,65 +1,92 @@
-# -*- coding: utf-8 -*-
-
-import unittest
-from jinja2 import Environment
-from pyramid.testing import DummyRequest
-
-class DummyRoot(object):
- __name__ = __parent__ = None
-
-class DummyModel(object):
- __name__ = 'dummy'
- __parent__ = DummyRoot()
-
-class Test_model_url_filter(unittest.TestCase):
- def setUp(self):
- self.environment = Environment()
- from pyramid_jinja2.filters import model_url_filter
- self.environment.filters['model_url'] = model_url_filter
- from pyramid.config import Configurator
- self.config = Configurator(autocommit=True)
- self.config.begin(request=DummyRequest())
-
- def tearDown(self):
- self.config.end()
-
- def _callFUT(self, context, tmpl):
- tmpl = self.environment.from_string(tmpl)
- return tmpl.render(**context)
-
-
- def test_filter(self):
- model = DummyModel()
- rendered = self._callFUT({'model':model}, '{{model|model_url}}')
- self.assertEqual(rendered, 'http://example.com/dummy/')
-
- def test_filter_with_elements(self):
- model = DummyModel()
- rendered = self._callFUT({'model':model}, "{{model|model_url('edit')}}")
- self.assertEqual(rendered, 'http://example.com/dummy/edit')
-
-class Test_route_url_filter(unittest.TestCase):
- def setUp(self):
- self.environment = Environment()
- from pyramid_jinja2.filters import route_url_filter
- self.environment.filters['route_url'] = route_url_filter
- from pyramid.config import Configurator
- self.config = Configurator(autocommit=True)
- self.config.begin(request=DummyRequest())
- self.config.add_route('dummy_route1', '/dummy/')
- self.config.add_route('dummy_route2', '/dummy/:name/')
-
- def tearDown(self):
- self.config.end()
-
- def _callFUT(self, context, tmpl):
- tmpl = self.environment.from_string(tmpl)
- return tmpl.render(**context)
-
- def test_filter(self):
- rendered = self._callFUT({}, "{{'dummy_route1' | route_url }}")
- self.assertEqual(rendered, 'http://example.com/dummy/')
-
- def test_filter_with_arguments(self):
- rendered = self._callFUT({}, "{{'dummy_route2' | route_url('x', name='test') }}")
- self.assertEqual(rendered, 'http://example.com/dummy/test/x')
+# -*- coding: utf-8 -*-
+
+import unittest
+from jinja2 import Environment
+from pyramid.testing import DummyRequest
+
+class DummyRoot(object):
+ __name__ = __parent__ = None
+
+class DummyModel(object):
+ __name__ = 'dummy'
+ __parent__ = DummyRoot()
+
+class Test_model_url_filter(unittest.TestCase):
+ def setUp(self):
+ self.environment = Environment()
+ from pyramid_jinja2.filters import model_url_filter
+ self.environment.filters['model_url'] = model_url_filter
+ from pyramid.config import Configurator
+ self.config = Configurator(autocommit=True)
+ self.config.begin(request=DummyRequest())
+
+ def tearDown(self):
+ self.config.end()
+
+ def _callFUT(self, context, tmpl):
+ tmpl = self.environment.from_string(tmpl)
+ return tmpl.render(**context)
+
+
+ def test_filter(self):
+ model = DummyModel()
+ rendered = self._callFUT({'model':model}, '{{model|model_url}}')
+ self.assertEqual(rendered, 'http://example.com/dummy/')
+
+ def test_filter_with_elements(self):
+ model = DummyModel()
+ rendered = self._callFUT({'model':model}, "{{model|model_url('edit')}}")
+ self.assertEqual(rendered, 'http://example.com/dummy/edit')
+
+class Test_route_url_filter(unittest.TestCase):
+ def setUp(self):
+ self.environment = Environment()
+ from pyramid_jinja2.filters import route_url_filter
+ self.environment.filters['route_url'] = route_url_filter
+ from pyramid.config import Configurator
+ self.config = Configurator(autocommit=True)
+ self.config.begin(request=DummyRequest())
+ self.config.add_route('dummy_route1', '/dummy/')
+ self.config.add_route('dummy_route2', '/dummy/:name/')
+
+ def tearDown(self):
+ self.config.end()
+
+ def _callFUT(self, context, tmpl):
+ tmpl = self.environment.from_string(tmpl)
+ return tmpl.render(**context)
+
+ def test_filter(self):
+ rendered = self._callFUT({}, "{{'dummy_route1' | route_url }}")
+ self.assertEqual(rendered, 'http://example.com/dummy/')
+
+ def test_filter_with_arguments(self):
+ rendered = self._callFUT({}, "{{'dummy_route2' | route_url('x', name='test') }}")
+ self.assertEqual(rendered, 'http://example.com/dummy/test/x')
+
+class Test_static_url_filter(unittest.TestCase):
+ def setUp(self):
+ self.environment = Environment()
+ from pyramid_jinja2.filters import static_url_filter
+ self.environment.filters['static_url'] = static_url_filter
+ from pyramid.config import Configurator
+ self.config = Configurator(autocommit=True)
+ self.config.begin(request=DummyRequest())
+ self.config.add_static_view('myfiles', 'dummy1:static')
+ self.config.add_static_view('otherfiles/{owner}', 'dummy2:files')
+
+ def tearDown(self):
+ self.config.end()
+
+ def _callFUT(self, context, tmpl):
+ tmpl = self.environment.from_string(tmpl)
+ return tmpl.render(**context)
+
+ def test_filter(self):
+ rendered = self._callFUT({}, "{{'dummy1:static/the/quick/brown/fox.svg' | static_url }}")
+ self.assertEqual(rendered, 'http://example.com/myfiles/the/quick/brown/fox.svg')
+
+ def test_filter_with_arguments(self):
+ rendered = self._callFUT({}, "{{'dummy2:files/report.txt' | static_url(owner='foo') }}")
+ self.assertEqual(rendered, 'http://example.com/otherfiles/foo/report.txt')
+
Something went wrong with that request. Please try again.