Skip to content

Commit

Permalink
Allow simplified setting DJANGOCMS_LINK_LINKABLE_MODELS.
Browse files Browse the repository at this point in the history
  • Loading branch information
fsbraun committed Oct 27, 2024
1 parent 106f4ac commit 393d2cb
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 12 deletions.
49 changes: 41 additions & 8 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ For a manual install:
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.

Expand All @@ -77,6 +80,32 @@ 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``.


Linkable models
...............

*Changed 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_fields``
attribute. 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 the autodetection, you can provide a list of models
in the ``DJANGOCMS_LINKABLE_MODELS`` setting using dotted strings::

DJANGOCMS_LINKABLE_MODELS = [
'myapp.mymodel',
]

Attention: ``Page`` objects are always linkable.

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.
Expand Down Expand Up @@ -109,17 +138,23 @@ models or forms.
from djangocms_link.fields import LinkField, LinkFormField, LinkWidget
class MyModel(models.Model):
link = LinkField()
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 dict.
(An empty link will be ``{}``.)

To render the link field in a template, use the new template tags::

{% load djangocms_link_tags %}
<a href="{{ obj.link|to_url }}">Link</a>
{# Variant 1 #}
{% if obj.link %}
<a href="{{ obj.link|to_url }}">Link</a>
{% endif %}

{# Variant 2 #}
{% get_url obj.link as url %}
{% if url %}
<a href="{{ url }}">Link available</a>
Expand Down Expand Up @@ -169,9 +204,7 @@ version 4 or lower, you will notice
Migrations should automatically existing plugin instances to the new model
fields.

.. warning::

Migration has worked for some people seamlessly. We strongly recommend to
backup your database before updating to version 5. If you encounter any
issues, please report them on
`GitHub <https://github.com/django-cms/djangocms-link/issues>`_.
**WARNING:** We strongly recommend to backup your database before updating to
version 5. The migrations have been tests but they do remove unused fields from
the database. If you encounter any issues, please report them on
`GitHub <https://github.com/django-cms/djangocms-link/issues>`_.
2 changes: 1 addition & 1 deletion djangocms_link/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
class GrouperModelAdmin:
pass

REGISTERED_ADMIN = getattr(settings, "DJANGOCMS_LINK_URL_ADMINS", "auto")
REGISTERED_ADMIN = getattr(settings, "DJANGOCMS_LINKABLE_MODELS", "auto")


class AdminUrlsView(BaseListView):
Expand Down
22 changes: 20 additions & 2 deletions djangocms_link/apps.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from django.apps import AppConfig
from django.apps import AppConfig, apps
from django.contrib.admin import ModelAdmin
from django.core.exceptions import ImproperlyConfigured
from django.utils.translation import gettext_lazy as _


Expand All @@ -12,7 +14,7 @@ def ready(self):

from djangocms_link import admin as link_admin

if link_admin.REGISTERED_ADMIN == "auto":
if link_admin.REGISTERED_ADMIN == "auto": # pragma: no cover
# Autoconfig? Check the admin registry for suitable admins
link_admin.REGISTERED_ADMIN = []
for _admin in admin.site._registry.values():
Expand All @@ -23,3 +25,19 @@ def ready(self):
# a get_absolute_url method.
if getattr(_admin, "search_fields", []) and hasattr(_admin.model, "get_absolute_url"):
link_admin.REGISTERED_ADMIN.append(_admin)
else:
# turn model config into model admin instances
admins = []
for model in link_admin.REGISTERED_ADMIN:
if isinstance(model, str):
model = apps.get_model(model)
if not hasattr(model, "get_absolute_url"): # pragma: no cover
raise ImproperlyConfigured(f"{model.__name__} needs to implement get_absolute_url method")
admin = admin.site.get_model_admin(model)
if admin not in admins:
admins.append(admin)
elif not isinstance(model, ModelAdmin): # pragma: no cover
raise ImproperlyConfigured(
"DJANGOCMS_LINK_LINKABLE_MODELS must be a list of string \"app_label.model_name\""
)
link_admin.REGISTERED_ADMIN = admins
3 changes: 2 additions & 1 deletion tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
('static_placeholder.html', 'Page with static placeholder'),
),
'FILE_UPLOAD_TEMP_DIR': mkdtemp(),
'CMS_CONFIRM_VERSION4': True
'CMS_CONFIRM_VERSION4': True,
'DJANGOCMS_LINKABLE_MODELS': ["utils.thirdpartymodel"],
}


Expand Down
Empty file added tests/test_cms_config.py
Empty file.
6 changes: 6 additions & 0 deletions tests/utils/cms_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from cms.app_base import CMSAppConfig


class UtilCMSAppConfig(CMSAppConfig):
djangocms_link_enabled = True
djangocms_link_models = ["utils.thirdpartymodel"]

0 comments on commit 393d2cb

Please sign in to comment.