Link Plugin¶
djangocms-cascade ships with its own Link plugin. This is because other plugins from djangocms-cascade, such as ButtonPlugin, ImagePlugin or PicturePlugin require the functionality to set links to internal- and external URLs. The de-facto plugin for links, djangocms-link can’t be used as a base class for these plugins, therefore an alternative implementation has been created. And as all other Cascade plugins, the LinkPlugin also keeps its data in a JSON field.
Before using this plugin, assure that 'cmsplugin_cascade.link'
is member of the list or
tuple CMSPLUGIN_CASCADE_PLUGINS
in the project’s settings.py
.
The behavior of this Plugin is what you expect from a Link editor. The field Link Content is the
text displayed between the opening and closing <a>
tag. If used in combination with
djangocms-text-ckeditor the field automatically is filled out.
By changing the Link type, the user can choose between three types of Links:
- Internal Links pointing to another page inside the CMS.
- External Links pointing to a valid Internet URL.
- Links pointing to a valid e-mail address.
The optional field Title can be used to add a title="some value"
attribute to the
<a href ...>
element.
With Link Target, the user can specify, whether the linked content shall open in the current window or if the browser shall open a new window.
Link Plugin with sharable fields¶
If your web-site contains many links pointing onto external URLs, you might want to refer to them by a symbolic name, rather than having to reenter the URL repeatedly. With djangocms-cascade this can be achieved easily by declaring some of the plugin’s fields as “sharable”.
Assure that INSTALLED_APPS
contain 'cmsplugin_cascade.sharable'
, then redefine the
TextLinkPlugin to have sharable fields in settings.py
:
CMSPLUGIN_CASCADE = {
...
'plugins_with_sharables':
...
'TextLinkPlugin': ('link',), # and optionally other fields
...
},
...
}
This will change the Link Plugin’s editor slightly. Note the extra field added to the bottom of the form.
Now the URL for this ink entity is stored in a central entity. This feature is useful, if for instance the URL of an external web page may change in the future. Then the administrator can change that link in the administration area once, rather than having to go through all the pages and check if that link was used.
To retain the Link settings, click onto the checkbox Remember these settings as: ... and give it a name of your choice. The next time your create a Shared Link element, you may select a previously named settings from the select field Shared Settings. Since these settings can be shared among other plugins, these input fields are disabled and can’t be changed anymore.
Extending the Link Plugin¶
While programming third party modules for Django, one might have to access a model instance through a URL and thus add the method get_absolute_url to that Django model. Since such a URL is neither a CMS page, nor a URL to an external web page, it would be convenient to access that model using a special Link type.
For example, this special Link plugin is used by djangoSHOP to allow direct linking from a CMS page to a shop’s product.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | # -*- coding: utf-8 -*-
from django.utils.translation import ugettext_lazy as _
from django.apps import apps
from django.core.exceptions import ObjectDoesNotExist
from django_select2.fields import AutoModelSelect2Field
from cms.plugin_pool import plugin_pool
from cmsplugin_cascade.link.forms import TextLinkForm
from cmsplugin_cascade.link.models import SimpleLinkElement
from cmsplugin_cascade.link.plugin_base import TextLinkPluginBase
from cmsplugin_cascade.utils import resolve_dependencies
from shop.models.product import Product
class ProductSearchField(AutoModelSelect2Field):
empty_value = []
search_fields = ['product_code__startswith', 'translations__name__startswith']
queryset = Product.objects.all()
def security_check(self, request, *args, **kwargs):
user = request.user
if user and not user.is_anonymous() and user.is_staff:
return True
return False
def prepare_value(self, value):
if not value:
return None
return super(ProductSearchField, self).prepare_value(value)
class LinkForm(TextLinkForm):
LINK_TYPE_CHOICES = (('cmspage', _("CMS Page")), ('product', _("Product")), ('exturl', _("External URL")), ('email', _("Mail To")),)
product = ProductSearchField(required=False, label='',
help_text=_("An internal link onto a product from the shop"))
def clean_product(self):
if self.cleaned_data.get('link_type') == 'product':
self.cleaned_data['link_data'] = {
'type': 'product',
'model': 'shop.Product',
'pk': self.cleaned_data['product'] and self.cleaned_data['product'].pk or None,
}
def set_initial_product(self, initial):
try:
Model = apps.get_model(*initial['link']['model'].split('.'))
initial['product'] = Model.objects.get(pk=initial['link']['pk'])
except (KeyError, ObjectDoesNotExist):
pass
class LinkPlugin(TextLinkPluginBase):
model = SimpleLinkElement
fields = ('link_content', ('link_type', 'cms_page', 'product', 'ext_url', 'mail_to'), 'glossary',)
form = LinkForm
class Media:
js = resolve_dependencies('shop/js/admin/linkplugin.js')
plugin_pool.register_plugin(LinkPlugin)
|
When using this implementation, remember to change CMSPLUGIN_CASCADE_PLUGINS
in your project’s
settings.py
to that alternative Link plugin.
Now the select box for Link type will offer one additional option: “Product”. When this is selected, the site administrator can choose between all of the shops products.