Skip to content

Commit

Permalink
Add support for djangoCMS 4.x (#226)
Browse files Browse the repository at this point in the history
* fix: make Page queryies ready for djangocms 4.x

* feat: add support for djangoCMS 4

* tests: refactor tests for djangoCMS 4 support

* chore: extract 'django cms 4' compatibility function to reuse it between fields

* fix: isort the tests/ directory
  • Loading branch information
filipweidemann authored Jul 22, 2024
1 parent f8132ce commit 9d0a24b
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 13 deletions.
8 changes: 6 additions & 2 deletions djangocms_link/fields_select2.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

from django_select2.forms import ModelSelect2Widget

from djangocms_link.helpers import get_queryset_manager


class Select2PageSearchFieldMixin:
search_fields = [
Expand All @@ -27,9 +29,11 @@ def build_attrs(self, base_attrs, extra_attrs=None):
return attrs

def get_queryset(self):
# django CMS < 4
base_queryset = get_queryset_manager(Page.objects)
if self.site:
return Page.objects.drafts().on_site(self.site)
return Page.objects.drafts()
return base_queryset.on_site(self.site)
return base_queryset.all()

# we need to implement jQuery ourselves, see #180
class Media:
Expand Down
4 changes: 3 additions & 1 deletion djangocms_link/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

from djangocms_attributes_field.widgets import AttributesWidget

from djangocms_link.helpers import get_queryset_manager

from .fields import PageSearchField
from .models import Link

Expand All @@ -18,7 +20,7 @@ def for_site(self, site):
# current site
# this will work for PageSelectFormField
from cms.models import Page
self.fields['internal_link'].queryset = Page.objects.drafts().on_site(site)
self.fields['internal_link'].queryset = get_queryset_manager(Page.objects).on_site(site)
# set the current site as a internal_link field instance attribute
# this will be used by the field later to properly set up the queryset
# this will work for PageSearchField
Expand Down
4 changes: 4 additions & 0 deletions djangocms_link/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def get_queryset_manager(base):
if hasattr(base, "drafts"):
return base.drafts()
return base
71 changes: 71 additions & 0 deletions tests/fixtures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from django.apps import apps

from cms import __version__


DJANGO_CMS4 = not (__version__ < "4")
DJANGOCMS_VERSIONING = apps.is_installed("djangocms_versioning")


class TestFixture:
"""Sets up generic setUp and tearDown methods for tests."""

def setUp(self):
self.language = "en"
self.superuser = self.get_superuser()
return super().setUp()

def tearDown(self):
if DJANGOCMS_VERSIONING:
from djangocms_versioning.models import Version

Version.objects.all().delete()
return super().tearDown()

if DJANGO_CMS4: # CMS V4

def _get_version(self, grouper, version_state, language=None):
language = language or self.language

from djangocms_versioning.models import Version

versions = Version.objects.filter_by_grouper(grouper).filter(
state=version_state
)
for version in versions:
if (
hasattr(version.content, "language")
and version.content.language == language
):
return version
return None

def publish(self, grouper, language=None):
if DJANGOCMS_VERSIONING:
from djangocms_versioning.constants import DRAFT

version = self._get_version(grouper, DRAFT, language)
if version is not None:
version.publish(self.superuser)

def unpublish(self, grouper, language=None):
if DJANGOCMS_VERSIONING:
from djangocms_versioning.constants import PUBLISHED

version = self._get_version(grouper, PUBLISHED, language)
if version is not None:
version.unpublish(self.superuser)

def get_placeholders(self, page, language=None):
return page.get_placeholders(language or self.language)

else: # CMS V3

def publish(self, page, language=None):
page.publish(language)

def unpublish(self, page, language=None):
page.unpublish(language)

def get_placeholders(self, page, language=None):
return page.get_placeholders()
1 change: 1 addition & 0 deletions tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
('static_placeholder.html', 'Page with static placeholder'),
),
'FILE_UPLOAD_TEMP_DIR': mkdtemp(),
'CMS_CONFIRM_VERSION4': True
}


Expand Down
2 changes: 1 addition & 1 deletion tests/test_migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ def test_for_missing_migrations(self):
# the "no changes" exit code is 0
status_code = '0'

if status_code == '1':
if status_code == '1' and "djangocms_link" in output:
self.fail(f'There are missing migrations:\n {output.getvalue()}')
19 changes: 10 additions & 9 deletions tests/test_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
from djangocms_link.cms_plugins import LinkPlugin
from djangocms_link.models import AbstractLink

from .fixtures import TestFixture
from .helpers import get_filer_file


class LinkPluginsTestCase(CMSTestCase):
class LinkPluginsTestCase(TestFixture, CMSTestCase):

def setUp(self):
self.file = get_filer_file()
Expand All @@ -22,19 +23,19 @@ def setUp(self):
template="page.html",
language=self.language,
)
self.home.publish(self.language)
self.publish(self.home, self.language)
self.page = create_page(
title="content",
template="page.html",
language=self.language,
)
self.page.publish(self.language)
self.publish(self.page, self.language)
self.static_page = create_page(
title='static-content',
template='static_placeholder.html',
language='en',
)
self.placeholder = self.page.placeholders.get(slot="content")
self.placeholder = self.get_placeholders(self.page, self.language).get(slot="content")
self.superuser = self.get_superuser()

def tearDown(self):
Expand Down Expand Up @@ -64,7 +65,7 @@ def test_plugin_structure(self):
internal_link=self.page,
name="Page link",
)
self.page.publish(self.language)
self.publish(self.page, self.language)
self.assertEqual(plugin.get_plugin_class_instance().name, "Link")

with self.login_user_context(self.superuser):
Expand Down Expand Up @@ -97,7 +98,7 @@ def test_optional_link(self):
AbstractLink.link_is_optional = True

plugin = add_plugin(
self.page.placeholders.get(slot='content'),
self.get_placeholders(self.page, self.language).get(slot='content'),
'LinkPlugin',
'en',
)
Expand All @@ -108,7 +109,7 @@ def test_optional_link(self):
self.assertEqual(AbstractLink.link_is_optional, False)

plugin = add_plugin(
self.page.placeholders.get(slot='content'),
self.get_placeholders(self.page, self.language).get(slot='content'),
'LinkPlugin',
'en',
)
Expand All @@ -119,7 +120,7 @@ def test_optional_link(self):

def test_in_placeholders(self):
plugin = add_plugin(
self.page.placeholders.get(slot='content'),
self.get_placeholders(self.page, self.language).get(slot='content'),
'LinkPlugin',
'en',
internal_link=self.page,
Expand Down Expand Up @@ -164,7 +165,7 @@ def test_in_placeholders(self):

def test_file(self):
plugin = add_plugin(
self.page.placeholders.get(slot="content"),
self.get_placeholders(self.page, self.language).get(slot="content"),
"LinkPlugin",
"en",
file_link=self.file,
Expand Down
3 changes: 3 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ envlist =
isort
py{38,39,310}-dj{32}-cms{310,311}
py{38,39,310}-dj{40}-cms{311}
py{39,310}-dj{40,42}-cms{41}

skip_missing_interpreters=True

Expand All @@ -12,8 +13,10 @@ deps =
-r{toxinidir}/tests/requirements/base.txt
dj32: Django>=3.2,<4.0
dj40: Django>=4.0,<4.1
dj42: Django>=4.2,<5.0
cms310: django-cms>=3.10,<3.11
cms311: django-cms>=3.11,<3.12
cms41: django-cms>=4.1,<4.2
commands =
{envpython} --version
{env:COMMAND:coverage} erase
Expand Down

0 comments on commit 9d0a24b

Please sign in to comment.