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

Toby Dacre toby.okfn at gmail.com
Wed Jun 6 16:01:26 UTC 2012


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

>
>
> On 6/6/12 5:29 AM, "Sean Hammond" <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, 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
> http://lists.okfn.org/mailman/listinfo/ckan-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.okfn.org/pipermail/ckan-dev/attachments/20120606/f9cff214/attachment-0001.html>


More information about the ckan-dev mailing list