[ckan-dev] IDataSetForm.setup_template_variables vs. IPackageController.before_view

Haq, Salman Salman.Haq at neustar.biz
Tue Jun 12 10:57:43 UTC 2012


Toby,

ITemplateHelpers seem to do the trick and don't require me to think about the data flow for each incoming request as is the case with setup_template_variables and before_view.

Thanks,
Salman

From: Toby Dacre <toby.okfn at gmail.com<mailto:toby.okfn at gmail.com>>
Reply-To: CKAN Development Discussions <ckan-dev at lists.okfn.org<mailto:ckan-dev at lists.okfn.org>>
To: CKAN Development Discussions <ckan-dev at lists.okfn.org<mailto:ckan-dev at lists.okfn.org>>
Subject: Re: [ckan-dev] IDataSetForm.setup_template_variables vs. IPackageController.before_view



On 6 June 2012 15:29, Haq, Salman <Salman.Haq at neustar.biz<mailto:Salman.Haq at neustar.biz>> wrote:


On 6/6/12 5:29 AM, "Sean Hammond" <sean.hammond at okfn.org<mailto:sean.hammond at okfn.org>> wrote:

>> It seems that either function can be used to modify 'pkg_dict' which
>> is then passed to the templates to customize what is rendered.
>>
>> Which ones should be used and when?
>
>You can use your extension to test exactly when each function does and
>does not get called, but:
>
>It looks like setup_template_variables() is only called in a couple of
>places, when creating a new dataset and when editing a dataset (which
>makes sense as it's part of the IDatasetForm plugin which only gets used
>when there's a form involved). I'm not familiar with this function, but
>looking at the core extensions in ckan/ckanext, the method is used by
>the organizations extension to implement its custom dataset create/edit
>forms.
>
>before_view() is called whenever a package is dictized, including on the
>package read page and (I think) also on package list pages (e.g.
>dataset search results listings). But note that before_view() does not
>get called when accessing CKAN via the API, only when via the web UI.
>The purpose of before_view() is to allow extensions to modify the
>package dict before anything gets displayed to the user. For example, it
>is used by the multilingual extension to translate dataset fields like
>title, description, etc. into the user's selected language before
>displaying them.
>
>Hope that helps

Thank you for the detailed reply.

Consider the following use case:
Retrieve a statistic and display it on each page with the URL prefix
/dataset/{pkg_id}/. That is to say, on *each* of the dataset pages
accessible by the minor navigation items: 'View', 'Resources', 'Related',
'History', 'Settings', and 'Authorization'. The catch is that this
statistic is not part of 'pkg_dict' as returned by
model_dictize.package_dictize and has to be retrieved by special logic in
an extension. Assume layout.html has been overridden appropriately by this
extension, so it's a question of retrieving and passing the right data to
the template. Now suppose that said extension defines a plugin that
implements IPackageController and IDatasetForm interfaces. Turns out that
this is quite tricky.

Consider the callbacks that will occur when clicking on each of the minor
navigation items:

[View] - IPackageController.before_view, IPackageController.read
[Resources/Add Edit Resource] - IPackageController.read,
IDatasetForm.setup_template_variables
[Resources/<resource>] - IPackageController.read
[Related] - IPackageController.before_view, IPackageController.read
[History] - IPackageController.read
[Settings] - IPackageController.before_view, IPackageController.read
[Authorization] - IPackageController.read

There are several problems here:
 - Two methods can modify template context: IPackageController.before_view
(indirectly, via pkg_dict) and IDatasetForm.setup_template_variables
(directly).
 - It's not obvious which is called when.
 - They are not called for all menu items.
 - The only method that is called back every time is IPackageControll.read
but it CANNOT modify the template context directly or indirectly.

Generally speaking, an extension cannot reliably extend the concept of a
dataset because it is not always possible to retrieve and display
extension-specific data.

I would recommend changing the signature of the IPackageController.read
callback so it can modify the pkg_dict. However there are other approaches
to fixing the issue and I'd like to hear what other developers have to say.


Salman,

Assuming you are using ckan 1.7 then creating a helper function via the ITemplateHelpers plugin interface would do what I think you want

example

import ckan.plugins as p

class MyPlugin(p.SingletonPlugin):

    p.implements(p.IConfigurer)
    p.implements(p.ITemplateHelpers)

    def update_config(self, config):
        # add template directory
        p.toolkit.add_template_directory(config, 'templates')

    @classmethod
    def my_function(cls, param1=None, param2=None):
        # do some work
        data = {'some_param' : value, 'another_param' : another_value}
        return p.toolkit.render_snippet('template.html', data)

    def get_helpers(self):
        return {'my_extension_my_function': self.my_function}


then in a template we would add

h.my_extension_my_function(param1=c.pkg_dict.id<http://c.pkg_dict.id>, param2=some_other_data)

the html would be defined in this example in the extensions templates/template.html


Toby

Thanks,
Salman



_______________________________________________
ckan-dev mailing list
ckan-dev at lists.okfn.org<mailto:ckan-dev at lists.okfn.org>
http://lists.okfn.org/mailman/listinfo/ckan-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.okfn.org/pipermail/ckan-dev/attachments/20120612/96802e79/attachment-0001.html>


More information about the ckan-dev mailing list