django CMS Link
July 8, 2026 · View on GitHub
=============== django CMS Link
|pypi| |coverage| |python| |django| |djangocms|
django CMS Link is a plugin for django CMS <https://django-cms.org>_ that
lets you add links to your site — to other pages, external URLs, files, phone
numbers, email addresses, and more.
The plugin supports child plugins: if you add another plugin as a child, its content is used as the link's content instead of the link name.
This addon is compatible with Divio Cloud <http://divio.com>_.
.. image:: preview.gif
Requirements
django CMS Link has a weak dependency on django Filer: if
django Filer <http://django-filer.readthedocs.io/en/latest/installation.html>_
is installed and configured, you will also be able to link to files.
- django CMS 3.11 or higher
- djangocms-attributes-field 1.0 or higher
- django Filer (optional, for file links)
See dependencies in the pyproject.toml <https://github.com/django-cms/djangocms-link/blob/master/pyproject.toml>_ file
for the full list of dependencies.
Installation
For a manual install:
- run
pip install djangocms-link - add
djangocms_linkto yourINSTALLED_APPS - run
python manage.py migrate djangocms_link
Configuration
Link templates
Note that the provided templates are very minimal by design. You are encouraged to adapt and override them to your project's requirements.
This addon provides a default template for all instances. You can provide
additional template choices by adding a DJANGOCMS_LINK_TEMPLATES
setting:
.. code-block:: python
DJANGOCMS_LINK_TEMPLATES = [
('feature', _('Featured Version')),
]
You'll need to create the feature folder inside templates/djangocms_link/
otherwise you will get a template does not exist error. You can do this by
copying the default folder inside that directory and renaming it to
feature.
Link types
By default, django CMS Link provides three major link types: internal, external, and file link (if django-filer is installed).
Phone links or email links can be entered by using the tel: or mailto:
scheme, respectively, in the external link field.
By changing the DJANGOCMS_LINK_ALLOWED_LINK_TYPES setting you can limit
the type of links accepted. The default is::
DJANGOCMS_LINK_ALLOWED_LINK_TYPES = [
'internal_link', # Pages and other models
'external_link', # Hand-typed URLs
'file_link', # Files from django-filer
'tel', # Phone numbers as external links using the tel: scheme
'mailto', # Email addresses as external links using the mailto: scheme
'anchor', # Anchors in the current page as external links using #
]
Linkable models
Added in version 5:
By default, django CMS Link will autodetect which Django or django CMS models it can create internal links to. To make a model appear in the list of internal links, you need to
- register a model admin for the model and provide a
search_fieldsattribute. django CMS Link uses the same search logic as the Django admin. - provide a
get_absolute_url()method on the model. This method should return the URL of the model instance.
If you do not want to use auto detection, you can provide a list of models
in the DJANGOCMS_LINKABLE_MODELS setting using dotted strings::
DJANGOCMS_LINKABLE_MODELS = [
'myapp.mymodel',
]
Note: Page objects are always linkable.
django CMS Link will use the model admin's get_queryset method to retrieve
the list of objects. If you want to add custom filters, sorting or site
handling, you can add a get_link_queryset method to the model admin::
class MyModelAdmin(admin.ModelAdmin):
def get_link_queryset(self, request, site_id):
"""Only used by djangocms-link: returns queryset to select link targets from."""
qs = self.get_queryset(request)
return qs.filter(is_public=True)
Large search-sets
If you have a large number of internally linkable models, you can use the
DJANGOCMS_LINK_MINIMUM_INPUT_LENGTH setting to require a minimum number of
characters typed before the search is triggered. The higher the number, the
smaller the average result set size. The default is 0::
# Require at least 2 characters to be typed before searching for pages
DJANGOCMS_LINK_MINIMUM_INPUT_LENGTH = 2
By default django CMS Link will paginate the search results. You can change the
page size by setting the DJANGOCMS_LINK_PAGINATE_BY setting.
The default is 50::
# Show 100 results per "page"
DJANGOCMS_LINK_PAGINATE_BY = 100
Note that in the admin, paginated search results repeat the model's verbose name.
Site-selectors
For multi-site installations, django CMS Link provides a site selector. It can be
switched on or off by setting the DJANGOCMS_LINK_SITE_SELECTOR setting to
True or False. The default is False::
# Enable the site selector
DJANGOCMS_LINK_SITE_SELECTOR = True
Non-standard hostnames
To support environments where non-standard URLs would otherwise work, this project supports the defining of an additional RegEx pattern for validating the host-portion of the URL.
For example:
.. code-block:: python
# RFC1123 Pattern:
DJANGOCMS_LINK_INTRANET_HOSTNAME_PATTERN = r'[a-z,0-9,-]{1,15}'
This might accept a URL such as:
.. code-block:: html
http://SEARCHHOST/?q=some+search+string
If left undefined, the normal Django URLValidator will be used.
Link fields
Added in version 5:
django CMS Link provides a re-usable link model field, form field and form widget. This allows you to use the link field in your own models or admin forms.
.. code-block:: python
from djangocms_link.fields import LinkField, LinkFormField, LinkWidget
class MyModel(models.Model):
link = LinkField() # or LinkField(blank=True) for optional links
class MyForm(forms.Form):
link = LinkFormField(required=False)
LinkField is a subclass of JSONField and stores the link data as
djangocms_link.helpers.LinkDict, a direct subclass of dict.
(An empty link will be {}.)
To render the link field in a template, convert the LinkDict to a string,
use the LinkDict property url, or use the new template tag to_url.
The type property returns the link type::
{# Variant 1 #}
{% if obj.link %}
<a href="{{ obj.link }}">Link available</a> {# str(obj.link) gives the URL #}
{% endif %}
{# Variant 2 #}
{% if obj.link %}
<a href="{{ obj.link.url }}">Link</a> {# explicitly get the URL #}
{% endif %}
{% if obj.link.type == "external_link" %} {# evaluate link type #}
<a href="{{ obj.link.url }}">External link</a>
{% endif %}
To turn the LinkField's LinkDict dictionary into a URL in Python code,
use the url property. (It will hit the database if needed. Results are
cached.)::
obj = MyModel.objects.first()
url = obj.link.url
A LinkField used inside a CMS plugin will automatically show internal link targets in
the language of the plugin (which might differ from the edit dialog's language). This
follows the principle the all content in the dialog is shown in the object's language.
If you use LinkField in your own models, the default will be the current language.
Link models
The to_url template filter and the get_obj_link helper function can be
used to get the full URL for any Django model instance. This is useful on
multi-site installations. to_url assumes that the model instance's site is
found in its site_id attribute (falling back to node.site_id). If the
model belongs to a different site than the current one, it prepends the domain
name of that site.
Example::
{% load djangocms_link_tags %}
{% if obj %}
<a href="{{ obj|to_url }}">Link to object</a> {# will include the site domain if needed #}
{% endif %}
Running tests
You can run tests by executing::
virtualenv env
source env/bin/activate
pip install -r tests/requirements.txt
pytest
Upgrading from version 4 or lower
django CMS Link 5 is a rewrite of the plugin. If you are updating from version 4 or lower, you will notice
- the new re-usable link widget, greatly simplifying the user interface
- an improved management of multi-site situations, essentially avoiding the unnecessary addition of the host name to the URL in plugin instances that are not in a page placeholder (such as links on aliases or static placeholders)
- a re-usable admin endpoint for querying available links, which can be used by other apps such as djangocms-text
- links are now generated by template tags or template filters instead of the
model's
get_link()method. This allows multiple links in future models. Theget_link()method on the plugin's model is still available for backwards compatibility.
Migrations should automatically convert existing plugin instances to the new model fields.
WARNING: We strongly recommend backing up your database before updating to
version 5. The migration is tested, but it does remove unused fields from
the database. If you encounter any issues, please report them on
GitHub <https://github.com/django-cms/djangocms-link/issues>_.
Contributing
This is an open-source project. We'll be delighted to receive your
feedback in the form of issues and pull requests. Before submitting your
pull request, please review our contribution guidelines <http://docs.django-cms.org/en/latest/contributing/index.html>_.
We're grateful to all contributors who have helped create and maintain this package.
Contributors are listed in the contributors <https://github.com/django-cms/djangocms-link/graphs/contributors>_ section.
One of the easiest contributions you can make is helping to translate this addon on
Transifex <https://www.transifex.com/projects/p/djangocms-link/>_.
.. |pypi| image:: https://badge.fury.io/py/djangocms-link.svg :target: http://badge.fury.io/py/djangocms-link
.. |coverage| image:: https://codecov.io/gh/django-cms/djangocms-link/branch/master/graph/badge.svg :target: https://codecov.io/gh/django-cms/djangocms-link
.. |python| image:: https://img.shields.io/pypi/pyversions/djangocms-link :alt: PyPI - Python Version :target: https://pypi.org/project/djangocms-link/
.. |django| image:: https://img.shields.io/pypi/frameworkversions/django/djangocms-link :alt: PyPI - Django Versions from Framework Classifiers :target: https://www.djangoproject.com/
.. |djangocms| image:: https://img.shields.io/pypi/frameworkversions/django-cms/djangocms-link :alt: PyPI - django CMS Versions from Framework Classifiers :target: https://www.django-cms.org/