Hook->hooks since there's more than one of them :)
[mediagoblin.git] / docs / source / pluginwriter / api.rst
1 .. MediaGoblin Documentation
2
3 Written in 2013 by MediaGoblin contributors
4
5 To the extent possible under law, the author(s) have dedicated all
6 copyright and related and neighboring rights to this software to
7 the public domain worldwide. This software is distributed without
8 any warranty.
9
10 You should have received a copy of the CC0 Public Domain
11 Dedication along with this software. If not, see
12 <http://creativecommons.org/publicdomain/zero/1.0/>.
13
14
15 ==========
16 Plugin API
17 ==========
18
19 This documents the general plugin API.
20
21 Please note, at this point OUR PLUGIN HOOKS MAY AND WILL CHANGE.
22 Authors are encouraged to develop plugins and work with the
23 MediaGoblin community to keep them up to date, but this API will be a
24 moving target for a few releases.
25
26 Please check the release notes for updates!
27
28 :mod:`pluginapi` Module
29 -----------------------
30
31 .. automodule:: mediagoblin.tools.pluginapi
32 :members: get_config, register_routes, register_template_path,
33 register_template_hooks, get_hook_templates,
34 hook_handle, hook_runall, hook_transform
35
36 Configuration
37 -------------
38
39 Your plugin may define its own configuration defaults.
40
41 Simply add to the directory of your plugin a config_spec.ini file. An
42 example might look like::
43
44 [plugin_spec]
45 some_string = string(default="blork")
46 some_int = integer(default=50)
47
48 This means that when people enable your plugin in their config you'll
49 be able to provide defaults as well as type validation.
50
51
52 Context Hooks
53 -------------
54
55 View specific hooks
56 +++++++++++++++++++
57
58 You can hook up to almost any template called by any specific view
59 fairly easily. As long as the view directly or indirectly uses the
60 method ``render_to_response`` you can access the context via a hook
61 that has a key in the format of the tuple::
62
63 (view_symbolic_name, view_template_path)
64
65 Where the "view symbolic name" is the same parameter used in
66 ``request.urlgen()`` to look up the test. So say we're wanting to add
67 something to the context of the user's homepage. We look in
68 mediagoblin/user_pages/routing.py and see::
69
70 add_route('mediagoblin.user_pages.user_home',
71 '/u/<string:user>/',
72 'mediagoblin.user_pages.views:user_home')
73
74 Aha! That means that the name is ``mediagoblin.user_pages.user_home``.
75 Okay, so then we look at the view at the
76 ``mediagoblin.user_pages.user_home`` method::
77
78 @uses_pagination
79 def user_home(request, page):
80 # [...] whole bunch of stuff here
81 return render_to_response(
82 request,
83 'mediagoblin/user_pages/user.html',
84 {'user': user,
85 'user_gallery_url': user_gallery_url,
86 'media_entries': media_entries,
87 'pagination': pagination})
88
89 Nice! So the template appears to be
90 ``mediagoblin/user_pages/user.html``. Cool, that means that the key
91 is::
92
93 ("mediagoblin.user_pages.user_home",
94 "mediagoblin/user_pages/user.html")
95
96 The context hook uses ``hook_transform()`` so that means that if we're
97 hooking into it, our hook will both accept one argument, ``context``,
98 and should return that modified object, like so::
99
100 def add_to_user_home_context(context):
101 context['foo'] = 'bar'
102 return context
103
104 hooks = {
105 ("mediagoblin.user_pages.user_home",
106 "mediagoblin/user_pages/user.html"): add_to_user_home_context}
107
108
109 Global context hooks
110 ++++++++++++++++++++
111
112 If you need to add something to the context of *every* view, it is not
113 hard; there are two hooks hook that also uses hook_transform (like the
114 above) but make available what you are providing to *every* view.
115
116 Note that there is a slight, but critical, difference between the two.
117
118 The most general one is the ``'template_global_context'`` hook. This
119 one is run only once, and is read into the global context... all views
120 will get access to what are in this dict.
121
122 The slightly more expensive but more powerful one is
123 ``'template_context_prerender'``. This one is not added to the global
124 context... it is added to the actual context of each individual
125 template render right before it is run! Because of this you also can
126 do some powerful and crazy things, such as checking the request object
127 or other parts of the context before passing them on.