Get plugin data in custom template


#1

Hey there,

let’s assume we have a plugin with custom settings per event or registration (like https://github.com/bpedersen2/indico-checkin-webhook-plugin/). Now we want to access this data in a custom template (e.g. an email sent out after registration). How can we do that?

Best,
Markus


#2

You need to pass it as a kwarg when calling render_template().

To get the value of a setting, use YourPlugin.settings.get('name') or if you want to get all of them as a dict, use YourPlugin.settings.get_all(). If you have stuff stored in a custom table, simply query it via sqlalchemy.

BTW, I noticed this code in your plugin. You do not have to create your own EventSettingsProxy. Every plugin already has a event_settings attribute. If you search e.g. for default_event_settings in our plugins you can find some examples where/how this is used.


#3

Hey,

can’t we add some attribute or method dynamically to the “event” object to store the data? This way we have it available in every template that uses the event object.


#4

Nope. Let let us know where your are getting the data you want to show in a template, and where you are rendering the template that needs the data, and we can probably give you a better suggestion how to do it.


#5

We want to implement a plugin that contains several custom settings for an event, for instance a custom salutation in the mail templates. We use the configuration form of the event to set the data and then use it in the templates.


#6

OK, use get_all() (as mentioned above) to load all your event settings in an appropriate signal handler. Then assign it e.g. to g.my_plugin_data (from flask import g).

The g object from Flask is available in all templates and the data stored on it only lives during that particular request, so you can use that from within your templates.

There is just one small problem with what I just said: We currently don’t have a signal that runs before the request is being processed… I absolutely think that we should change this and add a signal that runs at the various step of the RH logic (before/after args, permissions and main logic processing).
And since you do need access to the Event, all the workaround I can imagine right now would require you to query the event again, which is of course not great…


#7

To continue this idea:

I added a registration_created signal just after

logger.info('New registration %s by %s', registration, session.user) 

in util.py of registration and got my plugin to load something into g.myplugindata. I printed it out, so the stuff was definitely stored in g. Then I tried to get this data in the _registration_summary_blocks.html file via {{g.myplugindata}} at some header. Unfortunately the data does not exist anymore at the time of loading the registration summary page. Any idea how to persist this or relocate the signal?


#8

I’d expect it to work… I can have a quick look tomorrow in the office.

In the meantime, have a look at {{ g is defined }} and {{ g }} in that template to see if it’s actually defined and what’s in it. Since the output may include < you need to “view page source” (not using the dev tools which only shows the DOM tree) to actually check the output of the second one.

Also, did you restart the dev server? Flask reloads templates in debug mode, BUT macros not reloaded in some cases and require a restart anyway.


#9

Good to know, I’ll took this code from some plugin example.


#10

I just saw that you were talking abotu the summary page and not about the email sent to the user. It makes sense that it’s not in g anymore since it’s a different page/request (you are redirected after registering). So the code that runs to show this page only what’s in RHRegistrationForm.


#11

Have a look at this PR I just opened (you can most likely apply this to the 2.0 codebase as well, even though the PR is against 2.1):


To provide data on the registration summary, you can then use this in your plugin:

def init(self):
    super(MyPlugin, self).init()
    from indico.modules.events.registration.controllers.display import RHRegistrationForm
    self.connect(signals.rh.before_process, self._whatever, sender=RHRegistrationForm)

def _whatever(self, cls, rh, **kwargs):
    from flask import g
    g.helloworld = 'test'

Via the rh argument you can also access e.g. rh.event and rh.registration (the latter is None if the user is not registered yet)