Skip to content
This repository

Support for plugins to register URL patterns #738

Closed
wants to merge 2 commits into from

4 participants

Mitar Jonas Obrist Martin Brochhaus Patrick Lauber
Mitar
mitar commented

I have added support for plugins to register URL patterns in a similar way as Django allows ModelAdmins to register their URLs. But as plugins extend ModelAdmins I used get_plugin_urls as a method name.

This is useful when plugin has to talk back to the admin, probably asynchronously.

Documentation is included.

Jonas Obrist
Collaborator
ojii commented

Not an accepted feature for 2.2, to keep the pull requests queue clean I'll close this

Martin Brochhaus

Can we discuss on this, even if it is closed?
Somehow I love the idea because instinctively I always want to create a CMSPlugin first, say for my News model, but then I realize that the model will need several views (like index, details, archive), so I switch to a AppHook instead. And then: What if I want to place my news on a page AND a contact form (for example in the footer), which needs several views as well - not possible (right?).

However having CMSPlugins with their own url tree would mean that it is very likely to have clashing URLs, isn't it? How are we gonna prevent this?

Patrick Lauber
Owner

I very much like the idea

Mitar
mitar commented

I solved clashing by having plugin URLs restricted to their namespace. Check the documentation commit above. So for example markup plugin have their URLs under: /admin/cms/page/plugin/<plugin name>/.

Of course this is open to discussion. I have tried both. And it is very simple to change it (just move plugin_pool.get_patterns() to urls.py). But then I noticed that this could clash with user generated content. So I decided that it is better that it is under admin and to make things simple I used the fact that Django CMS already registers with admin.

So those URLs are mostly meant for URLs which will not be directly visible to the user. For those which would be I think the best approach is AppHook as it allows user to customize where and how it wants them.

Jonas Obrist
Collaborator
ojii commented

I agree this is a very interesting idea and we should definitely consider it for 2.3.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
3  cms/admin/pageadmin.py
@@ -201,6 +201,9 @@ def get_urls(self):
201 201 pat(r'^(?P<object_id>\d+)/change_template/$', self.change_template), # copy dialog
202 202 )
203 203
  204 + if plugin_pool.get_all_plugins():
  205 + url_patterns += plugin_pool.get_patterns()
  206 +
204 207 url_patterns = url_patterns + super(PageAdmin, self).get_urls()
205 208 return url_patterns
206 209
11 cms/plugin_base.py
@@ -211,6 +211,17 @@ def icon_alt(self, instance):
211 211 the plugin object in a text editor.
212 212 """
213 213 return "%s - %s" % (unicode(self.name), unicode(instance))
  214 +
  215 + def get_plugin_urls(self):
  216 + """
  217 + Return URL patterns for which the plugin wants to register
  218 + views for.
  219 + """
  220 + return []
  221 +
  222 + def plugin_urls(self):
  223 + return self.get_plugin_urls()
  224 + plugin_urls = property(plugin_urls)
214 225
215 226 def __repr__(self):
216 227 return smart_str(self.name)
21 cms/plugin_pool.py
@@ -3,7 +3,11 @@
3 3 from cms.plugin_base import CMSPluginBase
4 4 from cms.utils.helpers import reversion_register
5 5 from django.conf import settings
  6 +from django.conf.urls.defaults import url, patterns, include
  7 +from django.template.defaultfilters import slugify
  8 +from django.utils.encoding import force_unicode
6 9 from django.utils.importlib import import_module
  10 +from django.utils.translation import get_language, deactivate_all, activate
7 11
8 12 class PluginPool(object):
9 13 def __init__(self):
@@ -95,7 +99,24 @@ def get_plugin(self, name):
95 99 """
96 100 self.discover_plugins()
97 101 return self.plugins[name]
  102 +
  103 + def get_patterns(self):
  104 + # We want untranslated name of the plugin for its slug so we deactivate translation
  105 + lang = get_language()
  106 + deactivate_all()
98 107
  108 + url_patterns = []
  109 + for plugin in self.get_all_plugins():
  110 + p = plugin()
  111 + slug = slugify(force_unicode(p.name))
  112 + url_patterns += patterns('',
  113 + url(r'^plugin/%s/' % (slug,), include(p.plugin_urls)),
  114 + )
  115 +
  116 + # Reactivate translation
  117 + activate(lang)
  118 +
  119 + return url_patterns
99 120
100 121 plugin_pool = PluginPool()
101 122
9 docs/extending_cms/api_references.rst
Source Rendered
@@ -25,6 +25,13 @@ cms.plugin_base
25 25
26 26 Custom form class to be used to edit this plugin.
27 27
  28 + .. method:: get_plugin_urls(instance)
  29 +
  30 + Returns URL patterns for which the plugin wants to register views for.
  31 + They are included under Django CMS admin (probably ``/admin/cms/page/``)
  32 + and further under ``/plugin/<plugin name>/``. Useful if your plugin
  33 + needs to asynchronously talk to the admin.
  34 +
28 35 .. attribute:: model
29 36
30 37 Is the CMSPlugin model we created earlier. If you don't need a model
@@ -105,4 +112,4 @@ menus.base
105 112 :param dict attr: Optional, dictionary of additional information to store on
106 113 this node.
107 114 :param bool visible: Optional, defaults to ``True``, whether this item is
108   - visible or not.
  115 + visible or not.

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.