Skip to content

Commit

Permalink
[#847] Update custom snippet example
Browse files Browse the repository at this point in the history
  • Loading branch information
Sean Hammond committed Nov 27, 2013
1 parent 9a0b71b commit cacb133
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 70 deletions.
1 change: 0 additions & 1 deletion ckan/controllers/home.py
Expand Up @@ -179,7 +179,6 @@ def db_to_form_schema(group_type=None):
c.group_package_stuff = dirty_cached_group_stuff

# END OF DIRTYNESS

return base.render('home/index.html', cache_force=True)

def license(self):
Expand Down
Empty file.
@@ -1,9 +1,9 @@
{% ckan_extends %}

{% block secondary_content %}

{% block featured_group %}
{{ h.recently_changed_packages_activity_stream() }}
{% endblock %}

{% block featured_organization %}
{% snippet 'snippets/example_theme_most_popular_groups.html' %}

{% endblock %}
@@ -1,13 +1,24 @@
{# Renders a list of the site's most popular groups. #}

<div class="box">
<section class="module">
<header class="module-heading">
<h3>Most popular groups</h3>
</header>
<div class="module-content">
{% snippet 'group/snippets/group_list.html',
groups=h.example_theme_most_popular_groups() %}
</div>
</section>
</div>
<h3>Most popular groups</h3>
<ul>
{% for group in h.example_theme_most_popular_groups() %}
<li>
<a href="{{ h.url_for('group_read', action='read', id=group.name) }}">
<h3>{{ group.display_name }}</h3>
</a>
{% if group.description %}
<p>
{{ h.markdown_extract(group.description, extract_length=80) }}
</p>
{% else %}
<p class="empty">{{ _('This group has no description') }}</p>
{% endif %}
{% if group.packages %}
<strong class="count">{{ ungettext('{num} Dataset', '{num} Datasets', group.packages).format(num=group.packages) }}</strong>
{% else %}
<span class="count">{{ _('0 Datasets') }}</span>
{% endif %}
</li>
{% endfor %}
</ul>
46 changes: 33 additions & 13 deletions doc/theming/templates.rst
Expand Up @@ -472,7 +472,7 @@ organization section replaced with a list of the most popular groups.
Simply displaying a list of group titles isn't very good. We want the groups to
be hyperlinked to their pages, and also to show some other information about
the group such as its description and logo image. To display our groups nicely,
we'll use CKAN's *template snippets*.
we'll use CKAN's *template snippets*...

.. _snippets:

Expand Down Expand Up @@ -517,7 +517,11 @@ As in the ``group_list.html`` docstring above, each snippet's docstring
should document the parameters it requires.

If you reload your `CKAN front page`_ in your web browser now, you should see
the groups rendered nicely.
the most popular groups rendered in the same style as the list of groups on
the ``/groups`` page.

This style isn't really what we want for our front page, each group is too big.
To render the groups in a custom style, we can define a custom snippet...


---------------------------------
Expand Down Expand Up @@ -545,15 +549,30 @@ Create a new directory |snippets_dir| containing a file named

.. literalinclude:: /../ckanext/example_theme/v10_custom_snippet/templates/snippets/example_theme_most_popular_groups.html

.. todo::
This code uses a Jinja2 ``for`` loop to render each of the groups, and calls a
number of CKAN's template helper functions:

* To hyperlink each group's name to the group's page, it calls
:py:func:`~ckan.lib.helpers.url_for`.

* If the group has a description, it calls
:py:func:`~ckan.lib.helpers.markdown_extract` to render the description
nicely.

* If the group doesn't have a description, it uses the :py:func:`_` function to
mark the ``'This group has no description'`` message for translation.
When the page is rendered in a user's web browser, this string will be shown
in the user's language (if there's a translation of the string into that
language).

Explain the HTML and CSS being used in the snippet above, and where it comes
from.
* When rendering the group's number of datasets, it uses the
:py:func:`ungettext` function to mark the message for translation with
localized handling of plural forms.

Now edit your |index.html| file and change it to use our new snippet instead of
the default one:
Now edit your |layout1.html| file and change it to use our new snippet instead
of the default one:

.. literalinclude:: /../ckanext/example_theme/v10_custom_snippet/templates/home/index.html
.. literalinclude:: /../ckanext/example_theme/v10_custom_snippet/templates/home/layout1.html

.. warning::

Expand All @@ -576,11 +595,12 @@ the default one:

.. note::

Snippets don't have access to the global template context variable, ``c``
(see :doc:`variables-and-functions`). Snippets *can* access other
global variables such as ``h``, ``app_globals`` and ``request``, as well as
any variables explicitly passed into the snippet by the parent template when
it calls the snippet with a ``{% snippet %}`` tag.
Snippets don't have access to the global template context variable,
:py:data:`c` (see :doc:`variables-and-functions`).
Snippets *can* access other global variables such as :py:data:`h`,
:py:data:`app_globals` and :py:data:`request`, as well as any variables
explicitly passed into the snippet by the parent template when it calls the
snippet with a ``{% snippet %}`` tag.


-------------------------
Expand Down
137 changes: 95 additions & 42 deletions doc/theming/variables-and-functions.rst
Expand Up @@ -5,61 +5,114 @@ Variables and functions available to templates
The following global variables and functions are available to all CKAN
templates in their top-level namespace:

``c``
The `Pylons template context object <http://pylonsbook.com/en/1.0/exploring-pylons.html?highlight=template%20context#context-object>`_,
a thread-safe object that the application can store request-specific
variables against without the variables associated with one HTTP request
getting confused with variables from another request.
.. py:data:: c
Using ``c`` in CKAN is discouraged, use template helper functions instead.
The `Pylons template context object <http://pylonsbook.com/en/1.0/exploring-pylons.html?highlight=template%20context#context-object>`_,
a thread-safe object that the application can store request-specific
variables against without the variables associated with one HTTP request
getting confused with variables from another request.

``c`` is not available to snippets.
Using ``c`` in CKAN is discouraged, use template helper functions instead.

``app_globals``
The `Pylons App Globals object <http://pylonsbook.com/en/1.0/exploring-pylons.html?highlight=template%20context#app-globals-object>`_,
an object that the application can store request-independent variables
against. Variables stored against ``app_globals`` are shared between all HTTP
requests.
``c`` is not available to snippets.

``h``
CKAN's :ref:`template helper functions <template helper functions>`, plus any
:ref:`custom template helper functions <custom template helper functions>`
provided by any extensions.
.. py:data:: app_globals
``request``
The `Pylons Request object <http://pylonsbook.com/en/1.0/exploring-pylons.html?highlight=request#request>`_,
contains information about the HTTP request that is currently being responded
to, including the request headers and body, URL parameters, the requested
URL, etc.
The `Pylons App Globals object <http://pylonsbook.com/en/1.0/exploring-pylons.html?highlight=template%20context#app-globals-object>`_,
an instance of the :py:class:`ckan.lib.app_globals.Globals` class.
The application can store request-independent variables
against the ``app_globals`` object.. Variables stored against
``app_globals`` are shared between all HTTP requests.

``response``
The `Pylons Response object <http://pylonsbook.com/en/1.0/exploring-pylons.html?highlight=request#response>`_,
contains information about the HTTP response that is currently being prepared
to be sent back to the user, including the HTTP status code, headers, cookies,
etc.
.. py:data:: h
``session``
The `Beaker session object <http://beaker.readthedocs.org/en/latest/>`_,
which contains information stored in the user's currently active session
cookie.
CKAN's :ref:`template helper functions <template helper functions>`, plus
any
:ref:`custom template helper functions <custom template helper functions>`
provided by any extensions.

``N_``
The ``gettext_noop()`` function.
.. py:data:: request
``_``
The ``ugettext()`` function.
The `Pylons Request object <http://pylonsbook.com/en/1.0/exploring-pylons.html?highlight=request#request>`_,
contains information about the HTTP request that is currently being
responded to, including the request headers and body, URL parameters, the
requested URL, etc.

``translator``
The ``gettext.NullTranslations`` object.
.. py:data:: response
``ungettext``
The ``ungettext()`` function.
The `Pylons Response object <http://pylonsbook.com/en/1.0/exploring-pylons.html?highlight=request#response>`_,
contains information about the HTTP response that is currently being
prepared to be sent back to the user, including the HTTP status code,
headers, cookies, etc.

``actions``
The :py:class:`ckan.model.authz.Action`
.. py:data:: session
.. todo:: Remove this? Doesn't appear to be used and doesn't look like
something we want.
The `Beaker session object <http://beaker.readthedocs.org/en/latest/>`_,
which contains information stored in the user's currently active session
cookie.

.. py:function:: _(value)
The `pylons.i18n.translation.ugettext(value) <http://docs.pylonsproject.org/projects/pylons-webframework/en/latest/modules/i18n_translation.html?highlight=ugettext#pylons.i18n.translation.ugettext>`_ function:

Mark a string for translation. Returns the localized unicode string of
value.

Mark a string to be localized as follows::

_('This should be in lots of languages')

.. py:function:: N_(value)
The `pylons.i18n.translation.gettext_noop(value) <http://docs.pylonsproject.org/projects/pylons-webframework/en/latest/modules/i18n_translation.html?highlight=gettext_noop#pylons.i18n.translation.gettext_noop>`_ function:

Mark a string for translation without translating it. Returns value.

Used for global strings, e.g.::

foo = N_('Hello')

class Bar:
def __init__(self):
self.local_foo = _(foo)

h.set_lang('fr')
assert Bar().local_foo == 'Bonjour'
h.set_lang('es')
assert Bar().local_foo == 'Hola'
assert foo == 'Hello'


.. py:function:: ungettext
The `pylons.i18n.translation.ungettext(singular, plural, n) <http://docs.pylonsproject.org/projects/pylons-webframework/en/latest/modules/i18n_translation.html?highlight=ungettext#pylons.i18n.translation.ungettext>`_
function:

Mark a string for translation. Returns the localized unicode string of the
pluralized value.

This does a plural-forms lookup of a message id. singular is used as the
message id for purposes of lookup in the catalog, while n is used to
determine which plural form to use. The returned message is a Unicode
string.

Mark a string to be localized as follows::

ungettext('There is %(num)d file here', 'There are %(num)d files here',
n) % {'num': n}

.. py:data:: translator
An instance of the `gettext.NullTranslations <http://docs.python.org/2/library/gettext.html#the-nulltranslations-class>`_
class. This is for internal use only, templates shouldn't need to use this.


.. py:class:: actions
The :py:class:`ckan.model.authz.Action` class.

.. todo:: Remove this? Doesn't appear to be used and doesn't look like
something we want.

In addition to the above, any variables explicitly passed into a template by a
controller action method when it calls ``render()`` will also be available to
Expand Down

0 comments on commit cacb133

Please sign in to comment.