diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f0bdec66..a7d3ac5f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog ========= +1.3.2 (2024-04-25) +================== + +* fix: make grid layout (rows/columns) compatible with flex box-based Django admin by @fsbraun in https://github.com/django-cms/djangocms-frontend/pull/208 +* fix: Improved handling of optional smart link field by @fsbraun in https://github.com/django-cms/djangocms-frontend/pull/210 + + 1.3.1 (2024-04-12) ================== diff --git a/djangocms_frontend/__init__.py b/djangocms_frontend/__init__.py index ad55976d..a9a6f9e7 100644 --- a/djangocms_frontend/__init__.py +++ b/djangocms_frontend/__init__.py @@ -19,4 +19,4 @@ 13. Github actions will publish the new package to pypi """ -__version__ = "1.3.1" +__version__ = "1.3.2" diff --git a/djangocms_frontend/common/attributes.py b/djangocms_frontend/common/attributes.py index 8fc8c969..4bc0d617 100644 --- a/djangocms_frontend/common/attributes.py +++ b/djangocms_frontend/common/attributes.py @@ -16,9 +16,7 @@ class AttributesMixin: def get_fieldsets(self, request, obj=None): meta = self.form._meta - fields = ( - ["tag_type"] if "tag_type" in getattr(meta, "untangled_fields", ()) else [] - ) + fields = ["tag_type"] if "tag_type" in getattr(meta, "untangled_fields", ()) else [] fields.append("attributes") return insert_fields( super().get_fieldsets(request, obj), diff --git a/djangocms_frontend/common/bootstrap5/background.py b/djangocms_frontend/common/bootstrap5/background.py index 2edabe7c..d930c808 100644 --- a/djangocms_frontend/common/bootstrap5/background.py +++ b/djangocms_frontend/common/bootstrap5/background.py @@ -47,9 +47,7 @@ class Meta: background_context = forms.ChoiceField( label=_("Background context"), required=False, - choices=settings.EMPTY_CHOICE - + settings.COLOR_STYLE_CHOICES - + (("transparent", _("Transparent")),), + choices=settings.EMPTY_CHOICE + settings.COLOR_STYLE_CHOICES + (("transparent", _("Transparent")),), initial=settings.EMPTY_CHOICE[0][0], widget=ColoredButtonGroup(), ) diff --git a/djangocms_frontend/common/bootstrap5/sizing.py b/djangocms_frontend/common/bootstrap5/sizing.py index 099b8208..7b754241 100644 --- a/djangocms_frontend/common/bootstrap5/sizing.py +++ b/djangocms_frontend/common/bootstrap5/sizing.py @@ -46,9 +46,7 @@ class Meta: initial=settings.EMPTY_CHOICE[0][0], choices=settings.EMPTY_CHOICE + settings.SIZE_X_CHOICES, # widget=ButtonGroup(attrs=dict(property="text")), - help_text=_( - "Sets the horizontal size relative to the surrounding container or the viewport." - ), + help_text=_("Sets the horizontal size relative to the surrounding container or the viewport."), ) size_y = forms.ChoiceField( label=_("Vertical size"), @@ -56,7 +54,5 @@ class Meta: initial=settings.EMPTY_CHOICE[0][0], choices=settings.EMPTY_CHOICE + settings.SIZE_Y_CHOICES, # widget=ButtonGroup(attrs=dict(property="text")), - help_text=_( - "Sets the vertical size relative to the surrounding container or the viewport." - ), + help_text=_("Sets the vertical size relative to the surrounding container or the viewport."), ) diff --git a/djangocms_frontend/common/spacing.py b/djangocms_frontend/common/spacing.py index fcdc0514..c4b98c55 100644 --- a/djangocms_frontend/common/spacing.py +++ b/djangocms_frontend/common/spacing.py @@ -28,12 +28,7 @@ def __init__(self, **kwargs): self.side_choices = kwargs.pop("side_choices") super().__init__( [ - IconGroup( - choices=[ - (self.property + side, verbose) - for side, verbose in self.side_choices - ] - ), + IconGroup(choices=[(self.property + side, verbose) for side, verbose in self.side_choices]), DivSelectWidget(choices=kwargs.pop("size_choices")), ], **kwargs, diff --git a/djangocms_frontend/common/title.py b/djangocms_frontend/common/title.py index f87606a1..e63c88db 100644 --- a/djangocms_frontend/common/title.py +++ b/djangocms_frontend/common/title.py @@ -36,9 +36,7 @@ def __init__(self, *args, **kwargs): def clean(self, value): if value[0] and not value[1]: - raise ValidationError( - _("Please add a title if you want to publish it."), code="incomplete" - ) + raise ValidationError(_("Please add a title if you want to publish it."), code="incomplete") return super().clean(value) def compress(self, data_list): diff --git a/djangocms_frontend/contrib/accordion/frameworks/bootstrap5.py b/djangocms_frontend/contrib/accordion/frameworks/bootstrap5.py index fd0a9fd9..4f308b72 100644 --- a/djangocms_frontend/contrib/accordion/frameworks/bootstrap5.py +++ b/djangocms_frontend/contrib/accordion/frameworks/bootstrap5.py @@ -15,9 +15,5 @@ def render(self, context, instance, placeholder): instance.add_classes("accordion-collapse collapse") if instance.accordion_item_open: instance.add_classes("show") - instance.font_size = ( - context["parent"] - .config.get("accordion_header_type", "") - .replace("h", "fs-") - ) + instance.font_size = context["parent"].config.get("accordion_header_type", "").replace("h", "fs-") return super().render(context, instance, placeholder) diff --git a/djangocms_frontend/contrib/alert/cms_plugins.py b/djangocms_frontend/contrib/alert/cms_plugins.py index ddf1375c..75194df1 100644 --- a/djangocms_frontend/contrib/alert/cms_plugins.py +++ b/djangocms_frontend/contrib/alert/cms_plugins.py @@ -13,9 +13,7 @@ @plugin_pool.register_plugin -class AlertPlugin( - mixin_factory("Alert"), AttributesMixin, ResponsiveMixin, SpacingMixin, CMSUIPlugin -): +class AlertPlugin(mixin_factory("Alert"), AttributesMixin, ResponsiveMixin, SpacingMixin, CMSUIPlugin): """ Components > "Alerts" Plugin https://getbootstrap.com/docs/5.0/components/alerts/ diff --git a/djangocms_frontend/contrib/alert/forms.py b/djangocms_frontend/contrib/alert/forms.py index b3365294..b9a4bd01 100644 --- a/djangocms_frontend/contrib/alert/forms.py +++ b/djangocms_frontend/contrib/alert/forms.py @@ -18,9 +18,7 @@ mixin_factory = settings.get_forms(alert) -class AlertForm( - mixin_factory("Alert"), ResponsiveFormMixin, SpacingFormMixin, EntangledModelForm -): +class AlertForm(mixin_factory("Alert"), ResponsiveFormMixin, SpacingFormMixin, EntangledModelForm): """ Components > "Alerts" Plugin https://getbootstrap.com/docs/5.0/components/alerts/ diff --git a/djangocms_frontend/contrib/card/forms.py b/djangocms_frontend/contrib/card/forms.py index 2a9826ff..2fe3e142 100644 --- a/djangocms_frontend/contrib/card/forms.py +++ b/djangocms_frontend/contrib/card/forms.py @@ -28,9 +28,7 @@ ) # card allow for a transparent color -CARD_COLOR_STYLE_CHOICES = settings.COLOR_STYLE_CHOICES + ( - ("transparent", _("Transparent")), -) +CARD_COLOR_STYLE_CHOICES = settings.COLOR_STYLE_CHOICES + (("transparent", _("Transparent")),) CARD_TEXT_STYLES = COLOR_STYLE_CHOICES + (("white", _("White")),) @@ -132,9 +130,7 @@ class Meta: label=_("Alignment"), choices=settings.EMPTY_CHOICE + CARD_ALIGNMENT_CHOICES, required=False, - widget=forms.HiddenInput() - if "card_alignment" in getattr(settings, "EXCL_CARD_PROP", ()) - else IconGroup(), + widget=forms.HiddenInput() if "card_alignment" in getattr(settings, "EXCL_CARD_PROP", ()) else IconGroup(), ) card_text_color = forms.ChoiceField( label=_("Text context"), @@ -148,9 +144,7 @@ class Meta: label=_("Full height"), initial=False, required=False, - help_text=_( - "If checked cards in one row will automatically extend to the full row height." - ), + help_text=_("If checked cards in one row will automatically extend to the full row height."), widget=forms.HiddenInput() if "card_full_height" in getattr(settings, "EXCL_CARD_PROP", ()) else forms.CheckboxInput, @@ -193,9 +187,7 @@ class Meta: label=_("Content alignment"), choices=settings.EMPTY_CHOICE + settings.ALIGN_CHOICES, required=False, - widget=forms.HiddenInput() - if "text_alignment" in getattr(settings, "EXCL_CARD_PROP", ()) - else IconGroup(), + widget=forms.HiddenInput() if "text_alignment" in getattr(settings, "EXCL_CARD_PROP", ()) else IconGroup(), ) attributes = AttributesFormField() tag_type = TagTypeFormField() diff --git a/djangocms_frontend/contrib/carousel/cms_plugins.py b/djangocms_frontend/contrib/carousel/cms_plugins.py index 31ba1c56..f5b11a93 100644 --- a/djangocms_frontend/contrib/carousel/cms_plugins.py +++ b/djangocms_frontend/contrib/carousel/cms_plugins.py @@ -49,9 +49,7 @@ class CarouselPlugin(mixin_factory("Carousel"), AttributesMixin, CMSUIPlugin): ] def get_render_template(self, context, instance, placeholder): - return get_plugin_template( - instance, "carousel", "carousel", CAROUSEL_TEMPLATE_CHOICES - ) + return get_plugin_template(instance, "carousel", "carousel", CAROUSEL_TEMPLATE_CHOICES) @plugin_pool.register_plugin diff --git a/djangocms_frontend/contrib/carousel/constants.py b/djangocms_frontend/contrib/carousel/constants.py index 54575003..7255c456 100644 --- a/djangocms_frontend/contrib/carousel/constants.py +++ b/djangocms_frontend/contrib/carousel/constants.py @@ -28,9 +28,7 @@ (18, 9), ) + tuple(getattr(settings, "DJANGOCMS_FRONTEND_CAROUSEL_ASPECT_RATIOS", tuple())) -CAROUSEL_ASPECT_RATIO_CHOICES = tuple( - (f"{x}x{y}", f"{x}x{y}") for x, y in CAROUSEL_ASPECT_RATIOS -) +CAROUSEL_ASPECT_RATIO_CHOICES = tuple((f"{x}x{y}", f"{x}x{y}") for x, y in CAROUSEL_ASPECT_RATIOS) CAROUSEL_TRANSITION_CHOICES = ( ("", _("Slide")), diff --git a/djangocms_frontend/contrib/carousel/forms.py b/djangocms_frontend/contrib/carousel/forms.py index 0e812904..594b99e8 100644 --- a/djangocms_frontend/contrib/carousel/forms.py +++ b/djangocms_frontend/contrib/carousel/forms.py @@ -111,19 +111,14 @@ class Meta: label=_("Wrap"), initial=True, required=False, - help_text=_( - "Whether the carousel should cycle continuously or have " "hard stops." - ), + help_text=_("Whether the carousel should cycle continuously or have " "hard stops."), ) carousel_aspect_ratio = forms.ChoiceField( label=_("Aspect ratio"), choices=settings.EMPTY_CHOICE + CAROUSEL_ASPECT_RATIO_CHOICES, required=False, initial=settings.EMPTY_CHOICE[0][0], - help_text=_( - "Determines width and height of the image " - "according to the selected ratio." - ), + help_text=_("Determines width and height of the image " "according to the selected ratio."), ) carousel_transition = forms.ChoiceField( label=_("Transition"), diff --git a/djangocms_frontend/contrib/carousel/frameworks/bootstrap5.py b/djangocms_frontend/contrib/carousel/frameworks/bootstrap5.py index 4c8df5e2..059ef5b7 100644 --- a/djangocms_frontend/contrib/carousel/frameworks/bootstrap5.py +++ b/djangocms_frontend/contrib/carousel/frameworks/bootstrap5.py @@ -17,9 +17,7 @@ def render(self, context, instance, placeholder): height = float(context.get("height") or CAROUSEL_DEFAULT_SIZE[1]) if parent.carousel_aspect_ratio: - aspect_width, aspect_height = tuple( - int(i) for i in parent.carousel_aspect_ratio.split("x") - ) + aspect_width, aspect_height = tuple(int(i) for i in parent.carousel_aspect_ratio.split("x")) height = width * aspect_height / aspect_width instance.add_classes("carousel-item") diff --git a/djangocms_frontend/contrib/carousel/models.py b/djangocms_frontend/contrib/carousel/models.py index 0906ab2d..77a0c0f9 100644 --- a/djangocms_frontend/contrib/carousel/models.py +++ b/djangocms_frontend/contrib/carousel/models.py @@ -51,10 +51,7 @@ def get_short_description(self): image_text = _("") elif self.rel_image.name: image_text = self.rel_image.name - elif ( - self.rel_image.original_filename - and os.path.split(self.rel_image.original_filename)[1] - ): + elif self.rel_image.original_filename and os.path.split(self.rel_image.original_filename)[1]: image_text = os.path.split(self.rel_image.original_filename)[1] else: image_text = "Image" diff --git a/djangocms_frontend/contrib/collapse/cms_plugins.py b/djangocms_frontend/contrib/collapse/cms_plugins.py index 945daa69..5763d81d 100644 --- a/djangocms_frontend/contrib/collapse/cms_plugins.py +++ b/djangocms_frontend/contrib/collapse/cms_plugins.py @@ -38,9 +38,7 @@ class CollapsePlugin(mixin_factory("Collapse"), AttributesMixin, CMSUIPlugin): @plugin_pool.register_plugin -class CollapseTriggerPlugin( - mixin_factory("CollapseTrigger"), AttributesMixin, CMSUIPlugin -): +class CollapseTriggerPlugin(mixin_factory("CollapseTrigger"), AttributesMixin, CMSUIPlugin): """ Component > "Collapse" Plugin https://getbootstrap.com/docs/5.0/components/collapse/ @@ -64,9 +62,7 @@ class CollapseTriggerPlugin( @plugin_pool.register_plugin -class CollapseContainerPlugin( - mixin_factory("CollapseContainer"), AttributesMixin, CMSUIPlugin -): +class CollapseContainerPlugin(mixin_factory("CollapseContainer"), AttributesMixin, CMSUIPlugin): """ Component > "Collapse Container" Plugin https://getbootstrap.com/docs/5.0/components/collapse/ diff --git a/djangocms_frontend/contrib/grid/forms.py b/djangocms_frontend/contrib/grid/forms.py index 7b672036..2504c160 100644 --- a/djangocms_frontend/contrib/grid/forms.py +++ b/djangocms_frontend/contrib/grid/forms.py @@ -182,19 +182,11 @@ def clean(self): super().clean() for size in settings.DEVICE_SIZES: if f"{size}_col" in self.cleaned_data: - if ( - isinstance(self.cleaned_data[f"{size}_col"], str) - and self.cleaned_data[f"{size}_col"].isnumeric() - ): - self.cleaned_data[f"{size}_col"] = int( - self.cleaned_data[f"{size}_col"] - ) + if isinstance(self.cleaned_data[f"{size}_col"], str) and self.cleaned_data[f"{size}_col"].isnumeric(): + self.cleaned_data[f"{size}_col"] = int(self.cleaned_data[f"{size}_col"]) else: raise ValidationError( - _( - 'Column size needs to be empty, "auto", or a ' - "number between 1 and %(cols)d" - ), + _('Column size needs to be empty, "auto", or a ' "number between 1 and %(cols)d"), params=dict(cols=GRID_SIZE), code="invalid_column", ) @@ -233,16 +225,12 @@ def clean(self): extra_fields_column[f"{size}_ms"] = forms.BooleanField( label="ms-auto" if size == "xs" else f"ms-{size}-auto", required=False, - widget=forms.HiddenInput() - if "{size}_ms" in getattr(settings, "EXCL_COL_PROP", ()) - else forms.CheckboxInput(), + widget=forms.HiddenInput() if "{size}_ms" in getattr(settings, "EXCL_COL_PROP", ()) else forms.CheckboxInput(), ) extra_fields_column[f"{size}_me"] = forms.BooleanField( label="me-auto" if size == "xs" else f"me-{size}-auto", required=False, - widget=forms.HiddenInput() - if "{size}_me" in getattr(settings, "EXCL_COL_PROP", ()) - else forms.CheckboxInput(), + widget=forms.HiddenInput() if "{size}_me" in getattr(settings, "EXCL_COL_PROP", ()) else forms.CheckboxInput(), ) GridColumnForm = type( diff --git a/djangocms_frontend/contrib/grid/frameworks/bootstrap5.py b/djangocms_frontend/contrib/grid/frameworks/bootstrap5.py index aa7389d2..8a263874 100644 --- a/djangocms_frontend/contrib/grid/frameworks/bootstrap5.py +++ b/djangocms_frontend/contrib/grid/frameworks/bootstrap5.py @@ -41,9 +41,7 @@ def get_grid_values(self): for device in settings.DEVICE_SIZES: for element in ("col", "order", "offset", "ms", "me"): size = getattr(self, f"{device}_{element}", None) - if isinstance(size, int) and ( - element == "col" or element == "order" or element == "offset" - ): + if isinstance(size, int) and (element == "col" or element == "order" or element == "offset"): if size == 0 and element == "col": # 0 represents auto size = "auto" if device == "xs": @@ -62,9 +60,7 @@ def get_grid_values(self): class GridColumnRenderMixin: def render(self, context, instance, placeholder): instance.add_classes( - f"col text-{instance.text_alignment}" - if instance.config.get("text_alignment", None) - else "col" + f"col text-{instance.text_alignment}" if instance.config.get("text_alignment", None) else "col" ) instance.add_classes(instance.column_alignment) instance.add_classes(get_grid_values(instance)) diff --git a/djangocms_frontend/contrib/grid/frameworks/foundation6.py b/djangocms_frontend/contrib/grid/frameworks/foundation6.py index 1eb30660..b9e8a04d 100644 --- a/djangocms_frontend/contrib/grid/frameworks/foundation6.py +++ b/djangocms_frontend/contrib/grid/frameworks/foundation6.py @@ -42,9 +42,7 @@ def get_grid_values(self): else: classes.append(f"{foundation_sizes.get(device, device)}-{size}") else: - classes.append( - f"{foundation_sizes.get(device, device)}-{element}-{size}" - ) + classes.append(f"{foundation_sizes.get(device, device)}-{element}-{size}") return classes diff --git a/djangocms_frontend/contrib/grid/models.py b/djangocms_frontend/contrib/grid/models.py index b0181ea9..2a4030fb 100644 --- a/djangocms_frontend/contrib/grid/models.py +++ b/djangocms_frontend/contrib/grid/models.py @@ -29,9 +29,7 @@ class Meta: _("GridContainer") def get_short_description(self): - text = self.config.get("plugin_title", {}).get("title", "") or self.config.get( - "attributes", {} - ).get("id", "") + text = self.config.get("plugin_title", {}).get("title", "") or self.config.get("attributes", {}).get("id", "") for item in GRID_CONTAINER_CHOICES[1:]: if item[0] == self.container_type: text += f" ({item[1]})" @@ -56,13 +54,9 @@ class Meta: _("GridRow") def get_short_description(self): - descr = self.config.get("plugin_title", {}).get("title", "") or self.config.get( - "attributes", {} - ).get("id", "") + descr = self.config.get("plugin_title", {}).get("title", "") or self.config.get("attributes", {}).get("id", "") column_count = len(self.child_plugin_instances or []) - column_count_str = ngettext( - "(1 column)", "(%(count)i columns)", column_count - ) % {"count": column_count} + column_count_str = ngettext("(1 column)", "(%(count)i columns)", column_count) % {"count": column_count} if descr: column_count_str = f"{descr} {column_count_str}" return column_count_str @@ -80,9 +74,7 @@ class Meta: _("GridColumn") def get_short_description(self): - text = self.config.get("plugin_title", {}).get("title", "") or self.config.get( - "attributes", {} - ).get("id", "") + text = self.config.get("plugin_title", {}).get("title", "") or self.config.get("attributes", {}).get("id", "") if self.xs_col: text += f" (col-{self.xs_col}) " diff --git a/djangocms_frontend/contrib/icon/cms_plugins.py b/djangocms_frontend/contrib/icon/cms_plugins.py index d7be2ed4..0fba9356 100644 --- a/djangocms_frontend/contrib/icon/cms_plugins.py +++ b/djangocms_frontend/contrib/icon/cms_plugins.py @@ -34,9 +34,9 @@ class IconPlugin( text_icon = ( '' ) diff --git a/djangocms_frontend/contrib/icon/conf.py b/djangocms_frontend/contrib/icon/conf.py index 715ed0f0..31b8e4fa 100644 --- a/djangocms_frontend/contrib/icon/conf.py +++ b/djangocms_frontend/contrib/icon/conf.py @@ -14,33 +14,33 @@ "fomantic-ui": "fomantic-ui-icons.css", } -ICON_LIBRARIES_SHOWN = getattr(settings, "DJANGOCMS_FRONTEND_ICONS_LIBRARIES_SHOWN", ( - "font-awesome", - "bootstrap-icons", - "material-icons-filled", - "material-icons-outlined", - "material-icons-round", - "material-icons-sharp", - "material-icons-two-tone", - "fomantic-ui", - "foundation-icons", - "elegant-icons", - "feather-icons", - "open-iconic", - "tabler-icons", - "weather-icons", -)) +ICON_LIBRARIES_SHOWN = getattr( + settings, + "DJANGOCMS_FRONTEND_ICONS_LIBRARIES_SHOWN", + ( + "font-awesome", + "bootstrap-icons", + "material-icons-filled", + "material-icons-outlined", + "material-icons-round", + "material-icons-sharp", + "material-icons-two-tone", + "fomantic-ui", + "foundation-icons", + "elegant-icons", + "feather-icons", + "open-iconic", + "tabler-icons", + "weather-icons", + ), +) ICON_LIBRARIES = getattr( settings, "DJANGOCMS_FRONTEND_ICON_LIBRARIES", { library: (f"{library}.min.json", ICON_CDN.get(library, f"{library}.css")) - for library in getattr( - settings, - "DJANGOCMS_FRONTEND_ICON_LIBRARIES_SHOWN", - ICON_LIBRARIES_SHOWN - ) + for library in getattr(settings, "DJANGOCMS_FRONTEND_ICON_LIBRARIES_SHOWN", ICON_LIBRARIES_SHOWN) }, ) diff --git a/djangocms_frontend/contrib/icon/fields.py b/djangocms_frontend/contrib/icon/fields.py index 3ecb6ecb..7f2ebd8d 100644 --- a/djangocms_frontend/contrib/icon/fields.py +++ b/djangocms_frontend/contrib/icon/fields.py @@ -29,8 +29,8 @@ def get_context(self, name, value, attrs): ( key, key.title(), - static(f'{VENDOR_PATH}/icons-libraries/{value[0]}'), - value[1] if "/" in value[1] else static(f'{VENDOR_PATH}/stylesheets/{value[1]}') + static(f"{VENDOR_PATH}/icons-libraries/{value[0]}"), + value[1] if "/" in value[1] else static(f"{VENDOR_PATH}/stylesheets/{value[1]}"), ) for key, value in ICON_LIBRARIES.items() ] diff --git a/djangocms_frontend/contrib/icon/forms.py b/djangocms_frontend/contrib/icon/forms.py index a6d3e7f5..3101196f 100644 --- a/djangocms_frontend/contrib/icon/forms.py +++ b/djangocms_frontend/contrib/icon/forms.py @@ -36,9 +36,7 @@ class Meta: "attributes", ] } - untangled_fields = ( - "tag_type", - ) + untangled_fields = ("tag_type",) icon = IconPickerField() icon_size = forms.ChoiceField( diff --git a/djangocms_frontend/contrib/icon/templatetags/icon_tags.py b/djangocms_frontend/contrib/icon/templatetags/icon_tags.py index 5eb1b3e6..a7136bc3 100644 --- a/djangocms_frontend/contrib/icon/templatetags/icon_tags.py +++ b/djangocms_frontend/contrib/icon/templatetags/icon_tags.py @@ -12,8 +12,6 @@ def add_css_for_icon(context, icon): css_link = ICON_LIBRARIES[icon.get("library")][1] if css_link: if "/" not in css_link: # static link? - css_link = static( - f"djangocms_frontend/icon/vendor/assets/stylesheets/{css_link}" - ) + css_link = static(f"djangocms_frontend/icon/vendor/assets/stylesheets/{css_link}") context["icon_css"] = css_link return context diff --git a/djangocms_frontend/contrib/image/cms_plugins.py b/djangocms_frontend/contrib/image/cms_plugins.py index 2ec38047..4fd8182e 100644 --- a/djangocms_frontend/contrib/image/cms_plugins.py +++ b/djangocms_frontend/contrib/image/cms_plugins.py @@ -38,7 +38,7 @@ class ImagePlugin( '' '' ) diff --git a/djangocms_frontend/contrib/image/forms.py b/djangocms_frontend/contrib/image/forms.py index b448658f..432675fe 100644 --- a/djangocms_frontend/contrib/image/forms.py +++ b/djangocms_frontend/contrib/image/forms.py @@ -122,26 +122,20 @@ class Meta: lazy_loading = forms.BooleanField( label=_("Load lazily"), required=False, - help_text=_( - "Use for images below the fold. This will load images only if user scrolls them into view. " - ), + help_text=_("Use for images below the fold. This will load images only if user scrolls them into view. "), ) width = forms.IntegerField( label=_("Width"), required=False, min_value=1, - help_text=_( - "The image width as number in pixels. " 'Example: "720" and not "720px".' - ), + help_text=_("The image width as number in pixels. " 'Example: "720" and not "720px".'), ) height = forms.IntegerField( label=_("Height"), required=False, min_value=1, - help_text=_( - "The image height as number in pixels. " 'Example: "720" and not "720px".' - ), + help_text=_("The image height as number in pixels. " 'Example: "720" and not "720px".'), ) alignment = forms.ChoiceField( label=_("Alignment"), @@ -160,9 +154,7 @@ class Meta: use_automatic_scaling = forms.BooleanField( label=_("Automatic scaling"), required=False, - help_text=_( - "Uses the placeholder dimensions to automatically calculate the size." - ), + help_text=_("Uses the placeholder dimensions to automatically calculate the size."), ) # ignores all other cropping options # throws validation error if other cropping options are selected @@ -176,16 +168,12 @@ class Meta: use_crop = forms.BooleanField( label=_("Crop image"), required=False, - help_text=_( - "Crops the image according to the thumbnail settings provided in the template." - ), + help_text=_("Crops the image according to the thumbnail settings provided in the template."), ) use_upscale = forms.BooleanField( label=_("Upscale image"), required=False, - help_text=_( - "Upscales the image to the size of the thumbnail settings in the template." - ), + help_text=_("Upscales the image to the size of the thumbnail settings in the template."), ) use_responsive_image = forms.ChoiceField( label=_("Use responsive image"), @@ -203,9 +191,7 @@ class Meta: to_field_name="id", label=_("Thumbnail options"), required=False, - help_text=_( - "Overrides width, height, and crop; scales up to the provided preset dimensions." - ), + help_text=_("Overrides width, height, and crop; scales up to the provided preset dimensions."), ) picture_fluid = forms.BooleanField( label=_("Responsive"), @@ -252,10 +238,7 @@ def clean(self): # you shall only set one image kind if not data.get("picture", False) and not data.get("external_picture", False): raise forms.ValidationError( - _( - "You need to add either an image, " - "or a URL linking to an external image." - ) + _("You need to add either an image, " "or a URL linking to an external image.") ) # certain cropping options do not work together, the following @@ -278,10 +261,7 @@ def clean(self): break if invalid_option_pair: - message = _( - "Invalid cropping settings. " - 'You cannot combine "{field_a}" with "{field_b}".' - ) + message = _("Invalid cropping settings. " 'You cannot combine "{field_a}" with "{field_b}".') message = message.format( field_a=self.fields[invalid_option_pair[0]].label, field_b=self.fields[invalid_option_pair[0]].label, diff --git a/djangocms_frontend/contrib/image/frameworks/bootstrap5.py b/djangocms_frontend/contrib/image/frameworks/bootstrap5.py index c425d99f..fa547064 100644 --- a/djangocms_frontend/contrib/image/frameworks/bootstrap5.py +++ b/djangocms_frontend/contrib/image/frameworks/bootstrap5.py @@ -23,9 +23,7 @@ def render(self, context, instance, placeholder): if instance.picture_thumbnail: instance.add_classes("img-thumbnail") if instance.parent and instance.parent.plugin_type == "CardPlugin": - instance.add_classes( - "card-img-top" if is_first_child(instance, instance.parent) else "card-img-bottom" - ) + instance.add_classes("card-img-top" if is_first_child(instance, instance.parent) else "card-img-bottom") elif instance.parent and instance.parent.plugin_type == "FigurePlugin": instance.add_classes("figure-img") return super().render(context, instance, placeholder) diff --git a/djangocms_frontend/contrib/image/image_save.py b/djangocms_frontend/contrib/image/image_save.py index 27faa268..e3659e47 100644 --- a/djangocms_frontend/contrib/image/image_save.py +++ b/djangocms_frontend/contrib/image/image_save.py @@ -9,10 +9,10 @@ def create_image_plugin(filename, file, parent_plugin, **kwargs): - # Set the FilerImageField value. from filer.settings import FILER_IMAGE_MODEL from filer.utils.loader import load_model + image_class = load_model(FILER_IMAGE_MODEL) image_obj = image_class(file=ContentFile(file.read(), name=filename)) image_obj.save() @@ -26,10 +26,12 @@ def create_image_plugin(filename, file, parent_plugin, **kwargs): ui_item=Image.__class__.__name__, config={}, ).initialize_from_form() - img.config.update({ - "picture": {"pk": image_obj.pk, "model": "filer.image"}, - "use_no_cropping": True, - }) + img.config.update( + { + "picture": {"pk": image_obj.pk, "model": "filer.image"}, + "use_no_cropping": True, + } + ) add_plugin(parent_plugin.placeholder, img) return img diff --git a/djangocms_frontend/contrib/image/models.py b/djangocms_frontend/contrib/image/models.py index fc74a0e4..c09966ea 100644 --- a/djangocms_frontend/contrib/image/models.py +++ b/djangocms_frontend/contrib/image/models.py @@ -133,9 +133,7 @@ def img_src(self): "size": picture_options["size"], "crop": picture_options["crop"], "upscale": picture_options["upscale"], - "subject_location": self.rel_image.subject_location - if self.rel_image - else (), + "subject_location": self.rel_image.subject_location if self.rel_image else (), } try: diff --git a/djangocms_frontend/contrib/jumbotron/cms_plugins.py b/djangocms_frontend/contrib/jumbotron/cms_plugins.py index 5090cfd2..e16de09e 100644 --- a/djangocms_frontend/contrib/jumbotron/cms_plugins.py +++ b/djangocms_frontend/contrib/jumbotron/cms_plugins.py @@ -48,6 +48,4 @@ class JumbotronPlugin( ] def get_render_template(self, context, instance, placeholder): - return get_plugin_template( - instance, "jumbotron", "jumbotron", settings.JUMBOTRON_TEMPLATE_CHOICES - ) + return get_plugin_template(instance, "jumbotron", "jumbotron", settings.JUMBOTRON_TEMPLATE_CHOICES) diff --git a/djangocms_frontend/contrib/jumbotron/forms.py b/djangocms_frontend/contrib/jumbotron/forms.py index 8f482cdf..ec47eaac 100644 --- a/djangocms_frontend/contrib/jumbotron/forms.py +++ b/djangocms_frontend/contrib/jumbotron/forms.py @@ -49,9 +49,7 @@ class Meta: label=_("Fluid"), initial=False, required=False, - help_text=_( - "Makes the jumbotron fill the full width of the container or window." - ), + help_text=_("Makes the jumbotron fill the full width of the container or window."), ) attributes = AttributesFormField() tag_type = TagTypeFormField() diff --git a/djangocms_frontend/contrib/link/apps.py b/djangocms_frontend/contrib/link/apps.py index 094e779a..212963e5 100644 --- a/djangocms_frontend/contrib/link/apps.py +++ b/djangocms_frontend/contrib/link/apps.py @@ -5,9 +5,3 @@ class LinkConfig(AppConfig): name = "djangocms_frontend.contrib.link" verbose_name = _("Link") - - def ready(self): - from .helpers import ( - ensure_select2_url_is_available, # Only import after apps are ready - ) - ensure_select2_url_is_available() diff --git a/djangocms_frontend/contrib/link/cms_plugins.py b/djangocms_frontend/contrib/link/cms_plugins.py index 9e36e9b9..c0182796 100644 --- a/djangocms_frontend/contrib/link/cms_plugins.py +++ b/djangocms_frontend/contrib/link/cms_plugins.py @@ -1,6 +1,7 @@ from cms.plugin_pool import plugin_pool from django.apps import apps from django.conf import settings as django_settings +from django.urls import path from django.utils.translation import gettext_lazy as _ from djangocms_frontend.helpers import get_plugin_template, insert_fields @@ -10,7 +11,7 @@ from ...common.attributes import AttributesMixin from ...common.spacing import SpacingMixin from .. import link -from . import forms, models +from . import forms, models, views from .constants import USE_LINK_ICONS mixin_factory = settings.get_renderer(link) @@ -18,9 +19,7 @@ UILINK_FIELDS = ( ("name", "link_type"), - ("site", "url_grouper") - if apps.is_installed("djangocms_url_manager") - else ("external_link", "internal_link"), + ("site", "url_grouper") if apps.is_installed("djangocms_url_manager") else ("external_link", "internal_link"), ("link_context", "link_size"), ("link_outline", "link_block"), "link_stretched", @@ -31,11 +30,7 @@ None, { "fields": ("template",) - + ( - UILINK_FIELDS + (("icon_left", "icon_right"),) - if USE_LINK_ICONS - else UILINK_FIELDS - ) + + (UILINK_FIELDS + (("icon_left", "icon_right"),) if USE_LINK_ICONS else UILINK_FIELDS) }, ), ] @@ -86,9 +81,7 @@ def get_fieldsets(self, request, obj=None): return fieldsets -class LinkPlugin( - mixin_factory("Link"), AttributesMixin, SpacingMixin, LinkPluginMixin, CMSUIPlugin -): +class LinkPlugin(mixin_factory("Link"), AttributesMixin, SpacingMixin, LinkPluginMixin, CMSUIPlugin): """ Components > "Button" Plugin https://getbootstrap.com/docs/5.0/components/buttons/ @@ -103,7 +96,7 @@ class LinkPlugin( text_icon = ( '' ) @@ -112,12 +105,15 @@ class LinkPlugin( fieldsets = UILINK_FIELDSET def get_render_template(self, context, instance, placeholder): - return get_plugin_template( - instance, "link", "link", settings.LINK_TEMPLATE_CHOICES - ) + return get_plugin_template(instance, "link", "link", settings.LINK_TEMPLATE_CHOICES) + + def get_plugin_urls(self): + return [ + path("autocomplete/", views.AutocompleteJsonView.as_view(), name="link_link_autocomplete"), + ] -if "djangocms_frontend.contrib.link" in django_settings.INSTALLED_APPS and 'LinkPlugin' not in plugin_pool.plugins: +if "djangocms_frontend.contrib.link" in django_settings.INSTALLED_APPS and "LinkPlugin" not in plugin_pool.plugins: # Only register plugin if in INSTALLED_APPS plugin_pool.register_plugin(LinkPlugin) diff --git a/djangocms_frontend/contrib/link/forms.py b/djangocms_frontend/contrib/link/forms.py index e704556b..1ad25c3d 100644 --- a/djangocms_frontend/contrib/link/forms.py +++ b/djangocms_frontend/contrib/link/forms.py @@ -1,6 +1,7 @@ import json from types import SimpleNamespace +from cms.utils.urlutils import admin_reverse from django import apps, forms from django.conf import settings as django_settings from django.contrib.admin.widgets import SELECT2_TRANSLATIONS, AutocompleteMixin @@ -9,7 +10,6 @@ from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.db import models from django.db.models.fields.related import ManyToOneRel -from django.urls import reverse from django.utils.encoding import force_str from django.utils.translation import get_language from django.utils.translation import gettext as _ @@ -32,7 +32,7 @@ from ...models import FrontendUIItem from .. import link from .constants import LINK_CHOICES, LINK_SIZE_CHOICES, TARGET_CHOICES -from .helpers import ensure_select2_url_is_available, get_choices, get_object_for_value +from .helpers import get_choices, get_object_for_value mixin_factory = settings.get_forms(link) @@ -54,9 +54,7 @@ def __init__(self, *args, **kwargs): HOSTNAME = getattr(settings, "DJANGOCMS_LINK_INTRANET_HOSTNAME_PATTERN", None) LINK_MODELS = getattr(django_settings, "DJANGOCMS_FRONTEND_LINK_MODELS", []) -MINIMUM_INPUT_LENGTH = getattr( - django_settings, "DJANGOCMS_FRONTEND_MINIMUM_INPUT_LENGTH", 0 -) +MINIMUM_INPUT_LENGTH = getattr(django_settings, "DJANGOCMS_FRONTEND_MINIMUM_INPUT_LENGTH", 0) class Select2jqWidget(AutocompleteMixin, forms.Select): @@ -65,22 +63,20 @@ class Select2jqWidget(AutocompleteMixin, forms.Select): def __init__(self, *args, **kwargs): if MINIMUM_INPUT_LENGTH: if "attrs" in kwargs: - kwargs["attrs"].setdefault( - "data-minimum-input-length", MINIMUM_INPUT_LENGTH - ) + kwargs["attrs"].setdefault("data-minimum-input-length", MINIMUM_INPUT_LENGTH) else: kwargs["attrs"] = {"data-minimum-input-length": MINIMUM_INPUT_LENGTH} kwargs.setdefault("admin_site", None) kwargs.setdefault( "field", - SimpleNamespace(name="", model=SimpleNamespace( - _meta=SimpleNamespace(app="djangocms_frontend", label="link") - )) + SimpleNamespace( + name="", model=SimpleNamespace(_meta=SimpleNamespace(app="djangocms_frontend", label="link")) + ), ) # Fake field properties for autocomplete field (unused by link) super().__init__(*args, **kwargs) def get_url(self): - return reverse("dcf_autocomplete:ac_view") + return admin_reverse("link_link_autocomplete") def build_attrs(self, base_attrs, extra_attrs=None): """ @@ -106,9 +102,7 @@ def build_attrs(self, base_attrs, extra_attrs=None): "data-allow-clear": json.dumps(not self.is_required), "data-placeholder": "", # Allows clearing of the input. "lang": i18n_name, - "class": attrs["class"] - + (" " if attrs["class"] else "") - + "admin-autocomplete", + "class": attrs["class"] + (" " if attrs["class"] else "") + "admin-autocomplete", } ) return attrs @@ -128,9 +122,7 @@ def prepare_value(self, value): if isinstance(value, dict): # Entangled dictionary? try: app_label, model = value["model"].rsplit(".", 1) - content_type = ContentType.objects.get( - app_label=app_label, model=model - ) + content_type = ContentType.objects.get(app_label=app_label, model=model) return f"{content_type.id}-{value['pk']}" except (TypeError, ValueError, KeyError, ObjectDoesNotExist): pass @@ -165,17 +157,13 @@ class Meta: site = forms.ModelChoiceField( label=_("Site"), queryset=Site.objects.all(), - widget=HtmlLinkSiteSelectWidget( - attrs={"data-placeholder": _("Select site")} - ), + widget=HtmlLinkSiteSelectWidget(attrs={"data-placeholder": _("Select site")}), required=False, ) url_grouper = forms.ModelChoiceField( label=_("Url"), queryset=UrlGrouper.objects.all(), - widget=HtmlLinkUrlSelectWidget( - attrs={"data-placeholder": _("Select URL object from list")} - ), + widget=HtmlLinkUrlSelectWidget(attrs={"data-placeholder": _("Select URL object from list")}), required=False, ) @@ -246,7 +234,6 @@ class Meta: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - ensure_select2_url_is_available() self.fields["internal_link"].choices = self.get_choices def get_choices(self): @@ -278,15 +265,9 @@ def clean(self): ) anchor_field_verbose_name = force_str(self.fields[anchor_field_name].label) anchor_field_value = self.cleaned_data.get(anchor_field_name, None) - link_fields = { - key: self.cleaned_data.get(key, None) for key in link_field_names - } - link_field_verbose_names = { - key: force_str(self.fields[key].label) for key in link_fields.keys() - } - provided_link_fields = { - key: value for key, value in link_fields.items() if value - } + link_fields = {key: self.cleaned_data.get(key, None) for key in link_field_names} + link_field_verbose_names = {key: force_str(self.fields[key].label) for key in link_fields.keys()} + provided_link_fields = {key: value for key, value in link_fields.items() if value} if len(provided_link_fields) > 1: # Too many fields have a value. @@ -308,9 +289,7 @@ def clean(self): if anchor_field_value: for field_name in provided_link_fields.keys(): if field_name not in field_names_allowed_with_anchor: - error_msg = _( - "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s" - ) % { + error_msg = _("%(anchor_field_verbose_name)s is not allowed together with %(field_name)s") % { "anchor_field_verbose_name": anchor_field_verbose_name, "field_name": link_field_verbose_names.get(field_name), } @@ -322,9 +301,7 @@ def clean(self): ) -class LinkForm( - mixin_factory("Link"), SpacingFormMixin, TemplateChoiceMixin, AbstractLinkForm -): +class LinkForm(mixin_factory("Link"), SpacingFormMixin, TemplateChoiceMixin, AbstractLinkForm): class Meta: model = FrontendUIItem entangled_fields = { @@ -358,9 +335,7 @@ class Meta: label=_("Stretch link"), required=False, initial=False, - help_text=_( - "Stretches the active link area to the containing block (with position: relative)." - ), + help_text=_("Stretches the active link area to the containing block (with position: relative)."), ) link_type = forms.ChoiceField( label=_("Type"), @@ -381,9 +356,7 @@ class Meta: choices=LINK_SIZE_CHOICES, initial=LINK_SIZE_CHOICES[1][0], # Medium required=False, - widget=ButtonGroup( - attrs=dict(property="link-size", label_class="btn-secondary") - ), + widget=ButtonGroup(attrs=dict(property="link-size", label_class="btn-secondary")), ) link_outline = forms.BooleanField( label=_("Outline"), diff --git a/djangocms_frontend/contrib/link/helpers.py b/djangocms_frontend/contrib/link/helpers.py index f25ed5e0..3f0fdd61 100644 --- a/djangocms_frontend/contrib/link/helpers.py +++ b/djangocms_frontend/contrib/link/helpers.py @@ -6,7 +6,6 @@ from django.contrib.admin import site from django.contrib.contenttypes.models import ContentType from django.core.exceptions import FieldError, ObjectDoesNotExist -from django.urls import NoReverseMatch, reverse from django.utils.encoding import force_str from django.utils.html import mark_safe @@ -99,11 +98,7 @@ def get_link_choices(request, term="", lang=None, nbsp=None): except FieldError: pass if objects is None: - objects = [ - item - for item in qs.all() - if (not isinstance(term, str)) or term.upper() in str(item).upper() - ] + objects = [item for item in qs.all() if (not isinstance(term, str)) or term.upper() in str(item).upper()] if objects: type_class = ContentType.objects.get_for_model(objects[0].__class__) available_objects.append( @@ -112,9 +107,7 @@ def get_link_choices(request, term="", lang=None, nbsp=None): "children": [ dict(id=f"{type_class.id}-{obj.id}", text=str(obj)) for obj in objects - if request is None - or model_admin - and model_admin.has_view_permission(request, obj=obj) + if request is None or model_admin and model_admin.has_view_permission(request, obj=obj) ], } ) @@ -124,30 +117,8 @@ def get_link_choices(request, term="", lang=None, nbsp=None): def get_choices(request, term="", lang=None) -> list: def to_choices(json): return list( - (elem["text"], to_choices(elem["children"])) - if "children" in elem - else (elem["id"], elem["text"]) + (elem["text"], to_choices(elem["children"])) if "children" in elem else (elem["id"], elem["text"]) for elem in json ) return to_choices(get_link_choices(request, term, lang, " ")) - - -def ensure_select2_url_is_available() -> None: - """Install the URLs""" - try: - reverse("dcf_autocomplete:ac_view") - except NoReverseMatch: # Not installed yet - urlconf_module = import_module(django_settings.ROOT_URLCONF) - from django.urls import clear_url_caches, include, path - - urlconf_module.urlpatterns = [ - path( - "@dcf-links/", - include( - "djangocms_frontend.contrib.link.urls", - namespace="dcf_autocomplete", - ), - ) - ] + urlconf_module.urlpatterns - clear_url_caches() diff --git a/djangocms_frontend/contrib/link/models.py b/djangocms_frontend/contrib/link/models.py index 6eacc939..fe1359ed 100644 --- a/djangocms_frontend/contrib/link/models.py +++ b/djangocms_frontend/contrib/link/models.py @@ -95,9 +95,7 @@ def get_link(self): else: link = "" - if ( - not getattr(self, "phone", None) and not getattr(self, "mailto", None) - ) and getattr(self, "anchor", None): + if (not getattr(self, "phone", None) and not getattr(self, "mailto", None)) and getattr(self, "anchor", None): link += f"#{self.anchor}" return link diff --git a/djangocms_frontend/contrib/link/urls.py b/djangocms_frontend/contrib/link/urls.py deleted file mode 100644 index dc9c6d6f..00000000 --- a/djangocms_frontend/contrib/link/urls.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.urls import path - -from . import views - -app_name = "djangocms_frontend" - -urlpatterns = [ - path("link:autocomplete", views.AutocompleteJsonView.as_view(), name="ac_view"), -] diff --git a/djangocms_frontend/contrib/listgroup/forms.py b/djangocms_frontend/contrib/listgroup/forms.py index fcb131fe..85eec0e6 100644 --- a/djangocms_frontend/contrib/listgroup/forms.py +++ b/djangocms_frontend/contrib/listgroup/forms.py @@ -63,9 +63,7 @@ class Meta: simple_content = forms.CharField( label=_("One line content"), required=False, - help_text=_( - "List item text. Is only show if this list item has no child plugins." - ), + help_text=_("List item text. Is only show if this list item has no child plugins."), ) list_context = forms.ChoiceField( label=_("Context"), diff --git a/djangocms_frontend/contrib/media/cms_plugins.py b/djangocms_frontend/contrib/media/cms_plugins.py index c60d5a6f..979c3198 100644 --- a/djangocms_frontend/contrib/media/cms_plugins.py +++ b/djangocms_frontend/contrib/media/cms_plugins.py @@ -12,9 +12,7 @@ @plugin_pool.register_plugin -class MediaPlugin( - mixin_factory("Media"), AttributesMixin, ResponsiveMixin, CMSUIPlugin -): +class MediaPlugin(mixin_factory("Media"), AttributesMixin, ResponsiveMixin, CMSUIPlugin): """ Layout > "Media" Plugin http://getbootstrap.com/docs/4.0/layout/media-object/ diff --git a/djangocms_frontend/contrib/navigation/cms_plugins.py b/djangocms_frontend/contrib/navigation/cms_plugins.py index 9deef2a8..f1c60005 100644 --- a/djangocms_frontend/contrib/navigation/cms_plugins.py +++ b/djangocms_frontend/contrib/navigation/cms_plugins.py @@ -55,9 +55,7 @@ class NavigationPlugin( ] def get_render_template(self, context, instance, placeholder): - return get_plugin_template( - instance, "navigation", "navigation", settings.NAVIGATION_TEMPLATE_CHOICES - ) + return get_plugin_template(instance, "navigation", "navigation", settings.NAVIGATION_TEMPLATE_CHOICES) def render(self, context, instance, placeholder): context["nav_template"] = instance.config.get("template", default_template) @@ -75,13 +73,16 @@ class PageTreePlugin( The PageTreePlugin class is a plugin for Django CMS that allows users to display a hierarchical tree-like structure of pages on the frontend. """ + name = _("Page tree") module = _("Frontend") model = models.PageTree form = forms.PageTreeForm change_form_template = "djangocms_frontend/admin/page_tree.html" allow_children = False - parent_classes = ["NavigationPlugin",] + parent_classes = [ + "NavigationPlugin", + ] fieldsets = [ ( None, @@ -90,9 +91,7 @@ class PageTreePlugin( ] def get_render_template(self, context, instance, placeholder): - return get_template_path( - "navigation", context.get("nav_template", default_template), "page_tree" - ) + return get_template_path("navigation", context.get("nav_template", default_template), "page_tree") def render(self, context, instance, placeholder): context["start_level"] = instance.config.get("start_level", 0) @@ -111,13 +110,16 @@ class NavBrandPlugin( This plugin allows the user to define a brand logo or text that will be displayed in the navigation header. Content is added through child plugins. """ + name = _("Brand") module = _("Frontend") model = models.NavBrand form = forms.NavBrandForm change_form_template = "djangocms_frontend/admin/brand.html" allow_children = True - parent_classes = ["NavigationPlugin",] + parent_classes = [ + "NavigationPlugin", + ] link_fieldset_position = -1 fieldsets = [ @@ -128,9 +130,7 @@ class NavBrandPlugin( ] def get_render_template(self, context, instance, placeholder): - return get_template_path( - "navigation", context.get("nav_template", default_template), "brand" - ) + return get_template_path("navigation", context.get("nav_template", default_template), "brand") @plugin_pool.register_plugin @@ -142,6 +142,7 @@ class NavContainerPlugin( """ The `NavContainerPlugin` class is a deprecated plugin without functionality. It will be removed. """ + name = _("Navigation container") module = _("Frontend") model = models.NavContainer @@ -181,6 +182,7 @@ class NavLinkPlugin( - `parent_classes` (list): List of parent plugin classes that this plugin can be nested within. - `child_classes` (list): List of child plugin classes that can be nested within this plugin. """ + name = _("Navigation link") module = _("Frontend") model = models.NavLink @@ -196,6 +198,4 @@ class NavLinkPlugin( ] def get_render_template(self, context, instance, placeholder): - return get_template_path( - "navigation", context.get("nav_template", default_template), "link" - ) + return get_template_path("navigation", context.get("nav_template", default_template), "link") diff --git a/djangocms_frontend/contrib/navigation/forms.py b/djangocms_frontend/contrib/navigation/forms.py index 2e6ed8bd..611d5d3c 100644 --- a/djangocms_frontend/contrib/navigation/forms.py +++ b/djangocms_frontend/contrib/navigation/forms.py @@ -80,9 +80,7 @@ class Meta: start_level = forms.IntegerField( label=_("Start level"), initial=0, - help_text=_( - "Start level of this page tree (0: root, 1: level below root, etc.)" - ), + help_text=_("Start level of this page tree (0: root, 1: level below root, etc.)"), ) attributes = AttributesFormField() diff --git a/djangocms_frontend/contrib/tabs/cms_plugins.py b/djangocms_frontend/contrib/tabs/cms_plugins.py index cf234f46..5969aa59 100644 --- a/djangocms_frontend/contrib/tabs/cms_plugins.py +++ b/djangocms_frontend/contrib/tabs/cms_plugins.py @@ -47,9 +47,7 @@ def get_render_template(self, context, instance, placeholder): @plugin_pool.register_plugin -class TabItemPlugin( - mixin_factory("TabItem"), AttributesMixin, PaddingMixin, CMSUIPlugin -): +class TabItemPlugin(mixin_factory("TabItem"), AttributesMixin, PaddingMixin, CMSUIPlugin): """ Components > "Navs - Tab Item" Plugin https://getbootstrap.com/docs/5.0/components/navs/ diff --git a/djangocms_frontend/contrib/utilities/cms_plugins.py b/djangocms_frontend/contrib/utilities/cms_plugins.py index c6d0f0de..f945c704 100644 --- a/djangocms_frontend/contrib/utilities/cms_plugins.py +++ b/djangocms_frontend/contrib/utilities/cms_plugins.py @@ -53,9 +53,7 @@ class EditorNotePlugin(mixin_factory("EditorNote"), CMSUIPlugin): @plugin_pool.register_plugin -class HeadingPlugin( - mixin_factory("Heading"), AttributesMixin, SpacingMixin, CMSUIPlugin -): +class HeadingPlugin(mixin_factory("Heading"), AttributesMixin, SpacingMixin, CMSUIPlugin): """Room for notes for editor only visible in edit mode""" name = _("Heading") diff --git a/djangocms_frontend/contrib/utilities/forms.py b/djangocms_frontend/contrib/utilities/forms.py index a92024a5..93c6b0cc 100644 --- a/djangocms_frontend/contrib/utilities/forms.py +++ b/djangocms_frontend/contrib/utilities/forms.py @@ -64,15 +64,11 @@ class Meta: def clean(self): super().clean() - if ( - self.cleaned_data["space_property"] == "p" - and self.cleaned_data["space_size"] == "auto" - ): + if self.cleaned_data["space_property"] == "p" and self.cleaned_data["space_size"] == "auto": raise ValidationError( { "space_property": _( - "Padding does not have an auto spacing. Either " - "switch to margin or a defined size." + "Padding does not have an auto spacing. Either " "switch to margin or a defined size." ), "space_size": _( "Padding does not have an auto spacing. Either " @@ -124,9 +120,7 @@ class Meta: heading_id = forms.CharField( label=_("ID"), required=False, - help_text=_( - "Fill in unique ID for table of contents. If empty heading will not appear in table of contents." - ), + help_text=_("Fill in unique ID for table of contents. If empty heading will not appear in table of contents."), ) heading_context = forms.ChoiceField( label=_("Heading context"), @@ -158,20 +152,14 @@ class Meta: list_attributes = AttributesFormField( label=_("List attributes"), - help_text=_( - "Attributes apply to the list for each level in the table of contents." - ), + help_text=_("Attributes apply to the list for each level in the table of contents."), ) link_attributes = AttributesFormField( label=_("Link attributes"), - help_text=_( - "Attributes apply to the link for each entry in the table of contents." - ), + help_text=_("Attributes apply to the link for each entry in the table of contents."), ) attributes = AttributesFormField( label=_("Item attributes"), - help_text=_( - "Attributes apply to the list items for each entry in the table of contents." - ), + help_text=_("Attributes apply to the list items for each entry in the table of contents."), ) diff --git a/djangocms_frontend/contrib/utilities/frameworks/bootstrap5.py b/djangocms_frontend/contrib/utilities/frameworks/bootstrap5.py index 5a5cbce6..b18ea356 100644 --- a/djangocms_frontend/contrib/utilities/frameworks/bootstrap5.py +++ b/djangocms_frontend/contrib/utilities/frameworks/bootstrap5.py @@ -1,9 +1,7 @@ class SpacingRenderMixin: def render(self, context, instance, placeholder): if not instance.space_device or instance.space_device == "xs": - instance.add_classes( - f"{instance.space_property}{instance.space_sides}-{instance.space_size}" - ) + instance.add_classes(f"{instance.space_property}{instance.space_sides}-{instance.space_size}") else: instance.add_classes( f"{instance.space_property}{instance.space_sides}-{instance.space_device}-{instance.space_size}" diff --git a/djangocms_frontend/contrib/utilities/templatetags/fe_utilities.py b/djangocms_frontend/contrib/utilities/templatetags/fe_utilities.py index 338dff21..af3ae03e 100644 --- a/djangocms_frontend/contrib/utilities/templatetags/fe_utilities.py +++ b/djangocms_frontend/contrib/utilities/templatetags/fe_utilities.py @@ -7,10 +7,6 @@ register = template.Library() -@register.inclusion_tag( - f"djangocms_frontend/{settings.framework}/toc.html", takes_context=True -) +@register.inclusion_tag(f"djangocms_frontend/{settings.framework}/toc.html", takes_context=True) def table_of_contents(context): - return dict( - TOC=create_tree(context.get("request", [])) - ) # Empty TOC if no request object available + return dict(TOC=create_tree(context.get("request", []))) # Empty TOC if no request object available diff --git a/djangocms_frontend/fields.py b/djangocms_frontend/fields.py index 5b15199a..fe1495ea 100644 --- a/djangocms_frontend/fields.py +++ b/djangocms_frontend/fields.py @@ -18,9 +18,7 @@ def __init__(self, *args, **kwargs): template_field = self.fields["template"] choices = template_field.choices instance = kwargs.get("instance", None) - if len(choices) == 1 and ( - instance is None or instance.config.get("template", "") == choices[0][0] - ): + if len(choices) == 1 and (instance is None or instance.config.get("template", "") == choices[0][0]): template_field.widget = forms.HiddenInput() @@ -33,9 +31,7 @@ class Media: class ColoredButtonGroup(ButtonGroup): # lgtm [py/missing-call-to-init] - option_template_name = ( - "djangocms_frontend/admin/widgets/button_group_color_option.html" - ) + option_template_name = "djangocms_frontend/admin/widgets/button_group_color_option.html" class Media: css = settings.ADMIN_CSS @@ -65,9 +61,7 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) -class OptionalDeviceChoiceField( - forms.MultipleChoiceField -): # lgtm [py/missing-call-to-init] +class OptionalDeviceChoiceField(forms.MultipleChoiceField): # lgtm [py/missing-call-to-init] def __init__(self, **kwargs): kwargs.setdefault("choices", settings.DEVICE_CHOICES) kwargs.setdefault("initial", None) @@ -90,9 +84,7 @@ class DeviceChoiceField(OptionalDeviceChoiceField): def clean(self, value): value = super().clean(value) if isinstance(value, list) and len(value) == 0: - raise ValidationError( - _("Please select at least one device size"), code="invalid" - ) + raise ValidationError(_("Please select at least one device size"), code="invalid") return value @@ -115,9 +107,7 @@ def __init__(self, *args, **kwargs): try: - fields.AttributesWidget( - sorted=True - ) # does djangocms-attributes-field support sorted param? + fields.AttributesWidget(sorted=True) # does djangocms-attributes-field support sorted param? CHOICESWIDGETPARAMS = dict(sorted=False) # use unsorted variant except TypeError: CHOICESWIDGETPARAMS = dict() # Fallback for djangocms-attributes-field < 2.1 @@ -137,11 +127,7 @@ def __init__(self, *args, **kwargs): def clean(self, value): if not value: raise ValidationError( - mark_safe( - _( - "Please enter at least one choice. Use the + symbol to add a choice." - ) - ), + mark_safe(_("Please enter at least one choice. Use the + symbol to add a choice.")), code="empty", ) return [(key, value) for key, value in value.items()] diff --git a/djangocms_frontend/helpers.py b/djangocms_frontend/helpers.py index 3ab51191..a5fc300e 100644 --- a/djangocms_frontend/helpers.py +++ b/djangocms_frontend/helpers.py @@ -25,9 +25,7 @@ def get_related_object(scope, field_name): return relobj -def insert_fields( - fieldsets, new_fields, block=None, position=-1, blockname=None, blockattrs=None -): +def insert_fields(fieldsets, new_fields, block=None, position=-1, blockname=None, blockattrs=None): """ creates a copy of fieldsets inserting the new fields either in the indexed block at the position, or - if no block is given - at the end @@ -53,9 +51,7 @@ def insert_fields( modify = copy.deepcopy(fieldsets[block]) fields = modify[1]["fields"] if position >= 0: - modify[1]["fields"] = ( - list(fields[:position]) + list(new_fields) + list(fields[position:]) - ) + modify[1]["fields"] = list(fields[:position]) + list(new_fields) + list(fields[position:]) else: modify[1]["fields"] = ( list(fields[: position + 1] if position != -1 else fields) @@ -108,9 +104,7 @@ def link_to_framework_doc(ui_item, topic): link = FRAMEWORK_PLUGIN_INFO.get(ui_item, {}).get(topic, None) if link: return mark_safe_lazy( - _( - 'Read more in the documentation.' - ).format(link=link) + _('Read more in the documentation.').format(link=link) ) return None @@ -121,9 +115,7 @@ def add_plugin(placeholder, plugin): placeholder.add_plugin(plugin) else: # CMS < v4 if plugin.parent: - plugin.position -= ( - plugin.parent.position + 1 - ) # Restart position counting at 0 + plugin.position -= plugin.parent.position + 1 # Restart position counting at 0 else: plugin.position -= 1 # 0-based counting in v3 plugin.save() diff --git a/djangocms_frontend/management/bootstrap4_migration.py b/djangocms_frontend/management/bootstrap4_migration.py index 1f885516..7db2b1c6 100644 --- a/djangocms_frontend/management/bootstrap4_migration.py +++ b/djangocms_frontend/management/bootstrap4_migration.py @@ -364,24 +364,18 @@ def a001_alignment(obj, new_obj, field): def m001_spacing_mixin(obj, new_obj, type): classes = new_obj.config["attributes"].get("class", "").split() if classes: - for size, _ in list(settings.SPACER_SIZE_CHOICES) + ( - [("auto", "auto")] if type == "margin" else [] - ): + for size, _ in list(settings.SPACER_SIZE_CHOICES) + ([("auto", "auto")] if type == "margin" else []): if f"{type[0]}-{size}" in classes: classes.remove(f"{type[0]}-{size}") classes.append(f"{type[0]}x-{size}") classes.append(f"{type[0]}y-{size}") for side, _ in settings.SPACER_X_SIDES_CHOICES: - if f"{type[0]}{side}-{size}" in classes and not new_obj.config.get( - f"{type}_x", None - ): + if f"{type[0]}{side}-{size}" in classes and not new_obj.config.get(f"{type}_x", None): new_obj.config[f"{type}_x"] = f"{type[0]}{side}-{size}" new_obj.config[f"{type}_devices"] = None classes.remove(f"{type[0]}{side}-{size}") for side, _ in settings.SPACER_Y_SIDES_CHOICES: - if f"{type[0]}{side}-{size}" in classes and not new_obj.config.get( - f"{type}_y", None - ): + if f"{type[0]}{side}-{size}" in classes and not new_obj.config.get(f"{type}_y", None): new_obj.config[f"{type}_y"] = f"{type[0]}{side}-{size}" new_obj.config[f"{type}_devices"] = None classes.remove(f"{type[0]}{side}-{size}") @@ -489,9 +483,7 @@ def t001_template(obj, new_obj, bs4_setting, dcf_setting): if not in_choices(obj.template, BS4): print(f"=> Template '{obj.template}' in {obj.plugin_type} (id: {obj.id})") print(f" but not declared in {bs4_setting}") - print( - " You will be able to edit the plugin but up saving the template will be changed." - ) + print(" You will be able to edit the plugin but up saving the template will be changed.") if not DCF and bs4_setting != dcf_setting: print(f" Remember to put {dcf_setting} in your settings.py") @@ -509,9 +501,7 @@ def t001_template(obj, new_obj, bs4_setting, dcf_setting): "M001-p": lambda x, y: m001_spacing_mixin(x, y, "padding"), "M002": m002_responsive_mixin, "M003": m003_background_mixin, - "T001_PICTURE": lambda x, y: t001_template( - x, y, "DJANGOCMS_PICTURE_TEMPLATES", "DJANGOCMS_PICTURE_TEMPLATES" - ), + "T001_PICTURE": lambda x, y: t001_template(x, y, "DJANGOCMS_PICTURE_TEMPLATES", "DJANGOCMS_PICTURE_TEMPLATES"), "T001_LINK": lambda x, y: t001_template( x, y, "DJANGOCMS_LINK_TEMPLATES", "DJANGOCMS_FRONTEND_LINK_TEMPLATE_CHOICES" ), diff --git a/djangocms_frontend/management/commands/subcommands/base.py b/djangocms_frontend/management/commands/subcommands/base.py index 91f1d07b..ee709fb5 100644 --- a/djangocms_frontend/management/commands/subcommands/base.py +++ b/djangocms_frontend/management/commands/subcommands/base.py @@ -38,9 +38,7 @@ def add_builtin_arguments(parser): "--pythonpath", help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".', ) - parser.add_argument( - "--traceback", action="store_true", help="Raise on CommandError exceptions" - ) + parser.add_argument("--traceback", action="store_true", help="Raise on CommandError exceptions") parser.add_argument( "--no-color", action="store_true", diff --git a/djangocms_frontend/management/commands/subcommands/frequency_analysis.py b/djangocms_frontend/management/commands/subcommands/frequency_analysis.py index eae903e6..b1dddb7a 100644 --- a/djangocms_frontend/management/commands/subcommands/frequency_analysis.py +++ b/djangocms_frontend/management/commands/subcommands/frequency_analysis.py @@ -10,10 +10,6 @@ class FrequencyAnalysis(SubcommandsCommand): command_name = "frequency_analysis" def handle(self, *args, **options): - analysis = ( - FrontendUIItem.objects.values("ui_item") - .annotate(count=Count("ui_item")) - .order_by("-count") - ) + analysis = FrontendUIItem.objects.values("ui_item").annotate(count=Count("ui_item")).order_by("-count") for element in analysis: self.stdout.write(f"{element['ui_item']:20}\t{element['count']:6}") diff --git a/djangocms_frontend/management/commands/subcommands/migrate.py b/djangocms_frontend/management/commands/subcommands/migrate.py index be27944c..b565df20 100644 --- a/djangocms_frontend/management/commands/subcommands/migrate.py +++ b/djangocms_frontend/management/commands/subcommands/migrate.py @@ -36,9 +36,7 @@ data_migration.update(icon_migration.data_migration) plugin_prefixes.append(icon_migration.plugin_prefix) -additional_migrations = getattr( - settings, "DJANGOCMS_FRONTEND_ADDITIONAL_MIGRATIONS", None -) +additional_migrations = getattr(settings, "DJANGOCMS_FRONTEND_ADDITIONAL_MIGRATIONS", None) if additional_migrations: if isinstance(additional_migrations, str): additional_migrations = [additional_migrations] @@ -78,11 +76,7 @@ def migrate_to_djangocms_frontend(apps, schema_editor): new_obj.depth = obj.depth new_obj.numchild = obj.numchild new_obj.path = obj.path - new_obj.plugin_type = ( - plugin_names[new_model] - if new_model in plugin_names - else new_model + "Plugin" - ) + new_obj.plugin_type = plugin_names[new_model] if new_model in plugin_names else new_model + "Plugin" # Add something like `new_obj.field_name = obj.field_name` for any field in the the new plugin for field in fields: if field in data_migration: @@ -92,11 +86,7 @@ def migrate_to_djangocms_frontend(apps, schema_editor): old_field, new_field = field.split(" -> ") else: old_field, new_field = field, field - value = ( - old_field[1:-1] - if old_field[0] == "(" - else getattr(obj, old_field) - ) + value = old_field[1:-1] if old_field[0] == "(" else getattr(obj, old_field) if value == "": value = None if new_field in new_obj_fields: @@ -110,9 +100,7 @@ def migrate_to_djangocms_frontend(apps, schema_editor): ), "pk": value.pk, } - elif isinstance( - value, models.QuerySet - ): # related many field + elif isinstance(value, models.QuerySet): # related many field value = { "model": "{}.{}".format( value.model._meta.app_label, @@ -179,8 +167,7 @@ def handle(self, *args, **options): if "djangocms_frontend_frontenduiitem" not in tables: self.stdout.write( self.style.ERROR( - "I cannot find djangocms-frontend's tables in the database. Did you run\n" - "./manage.py migrate ?" + "I cannot find djangocms-frontend's tables in the database. Did you run\n" "./manage.py migrate ?" ) ) return @@ -200,9 +187,7 @@ def migrate_to_djangocms_frontend(self): if any([prefix in plugin.plugin_type for prefix in plugin_prefixes]): if plugin.plugin_type not in not_migrated: not_migrated.append(plugin.plugin_type) - self.stdout.write( - self.style.WARNING(f"{plugin.plugin_type} not migrated.") - ) + self.stdout.write(self.style.WARNING(f"{plugin.plugin_type} not migrated.")) if not not_migrated: if changes: self.stdout.write(self.style.SUCCESS("Successfully migrated plugins.")) @@ -211,16 +196,8 @@ def migrate_to_djangocms_frontend(self): def check_for_link_targets(self): self.stdout.write() - self.stdout.write( - self.style.SUCCESS( - "Checking installed apps for potential link destinations" - ) - ) - self.stdout.write( - self.style.SUCCESS( - "=======================================================" - ) - ) + self.stdout.write(self.style.SUCCESS("Checking installed apps for potential link destinations")) + self.stdout.write(self.style.SUCCESS("=======================================================")) blog = False count = 0 for app, app_models in apps.all_models.items(): @@ -229,16 +206,12 @@ def check_for_link_targets(self): if hasattr(model, "get_absolute_url"): count += 1 self.stdout.write( - self.style.NOTICE( - f"App {app}'s {model.__name__} model is a suitable link destination." - ) + self.style.NOTICE(f"App {app}'s {model.__name__} model is a suitable link destination.") ) if app == "djangocms_blog": blog = True if count: - self.stdout.write( - self.style.SUCCESS(f"{count} potential link destinations found.") - ) + self.stdout.write(self.style.SUCCESS(f"{count} potential link destinations found.")) if blog: self.stdout.write(self.style.WARNING(blog_example)) else: diff --git a/djangocms_frontend/management/commands/subcommands/stale_references.py b/djangocms_frontend/management/commands/subcommands/stale_references.py index 32f575fd..acb4e758 100644 --- a/djangocms_frontend/management/commands/subcommands/stale_references.py +++ b/djangocms_frontend/management/commands/subcommands/stale_references.py @@ -21,15 +21,9 @@ def handle(self, *args, **options): if pages: for page in pages: self.stdout.write( - self.style.WARNING( - f"... on page #{page.id}, at {page.get_absolute_url()}" - ) + self.style.WARNING(f"... on page #{page.id}, at {page.get_absolute_url()}") ) else: - self.stdout.write( - self.style.WARNING( - f"... in placeholder #{ui_item.placeholder.id}" - ) - ) + self.stdout.write(self.style.WARNING(f"... in placeholder #{ui_item.placeholder.id}")) self.stdout.write(self.style.SUCCESS("Finished checking references")) diff --git a/djangocms_frontend/management/commands/subcommands/sync_permissions.py b/djangocms_frontend/management/commands/subcommands/sync_permissions.py index acd1e0db..9e0f81de 100644 --- a/djangocms_frontend/management/commands/subcommands/sync_permissions.py +++ b/djangocms_frontend/management/commands/subcommands/sync_permissions.py @@ -31,11 +31,7 @@ def handle(self, *args, **options): self.stdout.write(self.style.ERROR("Aborted.")) return - dcf_models = [ - m - for m in apps.get_models() - if m.__module__.startswith("djangocms_frontend.") - ] + dcf_models = [m for m in apps.get_models() if m.__module__.startswith("djangocms_frontend.")] reference_model = [m for m in dcf_models if m.__name__ == "FrontendUIItem"][0] dcf_models.remove(reference_model) ctype = ContentType.objects.get( @@ -49,9 +45,7 @@ def handle(self, *args, **options): reduced = permission_set.filter(user=user) reduced = [perm.codename.split("_")[0] for perm in reduced] if reduced: - self.stdout.write( - self.style.NOTICE(f"... has {', '.join(reduced)}") - ) + self.stdout.write(self.style.NOTICE(f"... has {', '.join(reduced)}")) for model in dcf_models: perms = _get_all_permissions(model._meta) for perm, name in perms: @@ -66,24 +60,14 @@ def handle(self, *args, **options): defaults=dict(name=name), ) if created: - self.stdout.write( - self.style.WARNING(f"Created permission {new_perm}") - ) + self.stdout.write(self.style.WARNING(f"Created permission {new_perm}")) if ok: - if not user.user_permissions.filter( - codename=new_perm.codename, content_type=ctype - ): - self.stdout.write( - self.style.NOTICE(f"Added {new_perm} for {user}") - ) + if not user.user_permissions.filter(codename=new_perm.codename, content_type=ctype): + self.stdout.write(self.style.NOTICE(f"Added {new_perm} for {user}")) user.user_permissions.add(new_perm) else: - if user.user_permissions.filter( - codename=new_perm.codename, content_type=ctype - ): - self.stdout.write( - self.style.WARNING(f"Removed {new_perm} for {user}") - ) + if user.user_permissions.filter(codename=new_perm.codename, content_type=ctype): + self.stdout.write(self.style.WARNING(f"Removed {new_perm} for {user}")) user.user_permissions.remove(new_perm) user.save() if "groups" in options["scope"]: @@ -92,9 +76,7 @@ def handle(self, *args, **options): reduced = permission_set.filter(group=group) reduced = [perm.codename.split("_")[0] for perm in reduced] if reduced: - self.stdout.write( - self.style.NOTICE(f"... has {', '.join(reduced)}") - ) + self.stdout.write(self.style.NOTICE(f"... has {', '.join(reduced)}")) for model in dcf_models: perms = _get_all_permissions(model._meta) for perm, name in perms: @@ -109,22 +91,12 @@ def handle(self, *args, **options): defaults=dict(name=name), ) if ok: - if not group.permissions.filter( - codename=new_perm.codename, content_type=ctype - ): - self.stdout.write( - self.style.NOTICE(f"Added {new_perm} for {group}") - ) + if not group.permissions.filter(codename=new_perm.codename, content_type=ctype): + self.stdout.write(self.style.NOTICE(f"Added {new_perm} for {group}")) group.permissions.add(new_perm) else: - if group.permissions.filter( - codename=new_perm.codename, content_type=ctype - ): - self.stdout.write( - self.style.WARNING( - f"Removed {new_perm} for {group}" - ) - ) + if group.permissions.filter(codename=new_perm.codename, content_type=ctype): + self.stdout.write(self.style.WARNING(f"Removed {new_perm} for {group}")) group.permissions.remove(new_perm) group.save() diff --git a/djangocms_frontend/management/icon_migration.py b/djangocms_frontend/management/icon_migration.py index 6f1c291b..2694251d 100644 --- a/djangocms_frontend/management/icon_migration.py +++ b/djangocms_frontend/management/icon_migration.py @@ -94,24 +94,18 @@ def i001_icon(obj, new_obj): def m001_spacing_mixin(obj, new_obj, type): classes = new_obj.config["attributes"].get("class", "").split() if classes: - for size, _ in list(settings.SPACER_SIZE_CHOICES) + ( - [("auto", "auto")] if type == "margin" else [] - ): + for size, _ in list(settings.SPACER_SIZE_CHOICES) + ([("auto", "auto")] if type == "margin" else []): if f"{type[0]}-{size}" in classes: classes.remove(f"{type[0]}-{size}") classes.append(f"{type[0]}x-{size}") classes.append(f"{type[0]}y-{size}") for side, _ in settings.SPACER_X_SIDES_CHOICES: - if f"{type[0]}{side}-{size}" in classes and not new_obj.config.get( - f"{type}_x", None - ): + if f"{type[0]}{side}-{size}" in classes and not new_obj.config.get(f"{type}_x", None): new_obj.config[f"{type}_x"] = f"{type[0]}{side}-{size}" new_obj.config[f"{type}_devices"] = None classes.remove(f"{type[0]}{side}-{size}") for side, _ in settings.SPACER_Y_SIDES_CHOICES: - if f"{type[0]}{side}-{size}" in classes and not new_obj.config.get( - f"{type}_y", None - ): + if f"{type[0]}{side}-{size}" in classes and not new_obj.config.get(f"{type}_y", None): new_obj.config[f"{type}_y"] = f"{type[0]}{side}-{size}" new_obj.config[f"{type}_devices"] = None classes.remove(f"{type[0]}{side}-{size}") diff --git a/djangocms_frontend/management/styled_link_migration.py b/djangocms_frontend/management/styled_link_migration.py index ea48feb8..2380fd2f 100644 --- a/djangocms_frontend/management/styled_link_migration.py +++ b/djangocms_frontend/management/styled_link_migration.py @@ -37,14 +37,10 @@ def s001_migrate_styled_link(obj, new_obj): pk=obj.int_destination_id, ) styles = obj.styles.all() - new_obj.config["attributes"] = { - "class": " ".join(style.link_class for style in styles) - } + new_obj.config["attributes"] = {"class": " ".join(style.link_class for style in styles)} for style in styles: obj.styles.remove(style) - new_obj.config["link_type"] = ( - "btn" if "btn" in new_obj.attributes["class"] else "link" - ) + new_obj.config["link_type"] = "btn" if "btn" in new_obj.attributes["class"] else "link" def s002_migrate_image_container(obj, new_obj): diff --git a/djangocms_frontend/models.py b/djangocms_frontend/models.py index 916232b7..d7eff722 100644 --- a/djangocms_frontend/models.py +++ b/djangocms_frontend/models.py @@ -56,9 +56,7 @@ def __init__(self, *args, **kwargs): def __getattr__(self, item): """Makes properties of plugin config available as plugin properties.""" - if ( - item[0] != "_" and item in self.config - ): # Avoid infinite recursion trying to get .config from db + if item[0] != "_" and item in self.config: # Avoid infinite recursion trying to get .config from db return self.config[item] return super().__getattribute__(item) @@ -85,10 +83,7 @@ def get_attributes(self): classes.update(self._additional_classes) if classes: attributes["class"] = " ".join(classes) - parts = ( - f'{item}="{conditional_escape(value)}"' if value else f"{item}" - for item, value in attributes.items() - ) + parts = (f'{item}="{conditional_escape(value)}"' if value else f"{item}" for item, value in attributes.items()) attributes_string = " ".join(parts) return mark_safe(" " + attributes_string) if attributes_string else "" @@ -102,13 +97,9 @@ def initialize_from_form(self, form=None): form = self.get_plugin_class().form if isinstance(form, type): # if is class form = form() # instantiate - entangled_fields = getattr( - getattr(form, "Meta", None), "entangled_fields", {} - ).get("config", ()) + entangled_fields = getattr(getattr(form, "Meta", None), "entangled_fields", {}).get("config", ()) for field in entangled_fields: - self.config.setdefault( - field, {} if field == "attributes" else form[field].initial or "" - ) + self.config.setdefault(field, {} if field == "attributes" else form[field].initial or "") return self def get_short_description(self): @@ -141,5 +132,6 @@ class FrontendUIItem(AbstractFrontendUIItem): None """ + class Meta: verbose_name = _("UI item") diff --git a/djangocms_frontend/settings.py b/djangocms_frontend/settings.py index 013384df..07ee1176 100644 --- a/djangocms_frontend/settings.py +++ b/djangocms_frontend/settings.py @@ -10,9 +10,7 @@ None, { "fields": (), - "description": _( - "There are no further settings for this plugin. Please press save." - ), + "description": _("There are no further settings for this plugin. Please press save."), }, ) ] @@ -80,9 +78,7 @@ framework = getattr(django_settings, "DJANGOCMS_FRONTEND_FRAMEWORK", "bootstrap5") theme = getattr(django_settings, "DJANGOCMS_FRONTEND_THEME", "djangocms_frontend") -framework_settings = importlib.import_module( - f"djangocms_frontend.frameworks.{framework}" -) +framework_settings = importlib.import_module(f"djangocms_frontend.frameworks.{framework}") DEVICE_SIZES = framework_settings.DEVICE_SIZES DEVICE_CHOICES = framework_settings.DEVICE_CHOICES @@ -126,22 +122,16 @@ def get_mixins(naming, theme_path, mixin_path): except ModuleNotFoundError: render_module = None - return lambda name: render_factory( - naming.format(name=name), theme_module, render_module - ) + return lambda name: render_factory(naming.format(name=name), theme_module, render_module) def get_renderer(my_module): if not isinstance(my_module, str): my_module = my_module.__name__ - return get_mixins( - "{name}RenderMixin", theme_render_path, f"{my_module}.frameworks.{framework}" - ) + return get_mixins("{name}RenderMixin", theme_render_path, f"{my_module}.frameworks.{framework}") def get_forms(my_module): if not isinstance(my_module, str): my_module = my_module.__name__ - return get_mixins( - "{name}FormMixin", theme_forms_path, f"{my_module}.frameworks.{framework}" - ) + return get_mixins("{name}FormMixin", theme_forms_path, f"{my_module}.frameworks.{framework}") diff --git a/djangocms_frontend/templatetags/frontend.py b/djangocms_frontend/templatetags/frontend.py index dab0cdbb..fa4d432a 100644 --- a/djangocms_frontend/templatetags/frontend.py +++ b/djangocms_frontend/templatetags/frontend.py @@ -21,9 +21,7 @@ def get_attributes(attribute_field, *add_classes): additional_classes = set() for classes in add_classes: if classes: - additional_classes.update( - classes.split() if isinstance(classes, str) else classes - ) + additional_classes.update(classes.split() if isinstance(classes, str) else classes) attrs = [] if attribute_field: for key, val in attribute_field.items(): @@ -89,9 +87,7 @@ def framework_info(context, item, as_json=True): if not framework_info: content_type_id = context.get("content_type_id", None) if content_type_id: # Get from content_type - model_name = ( - ContentType.objects.get(id=content_type_id).model_class().__name__ - ) + model_name = ContentType.objects.get(id=content_type_id).model_class().__name__ framework_info = settings.FRAMEWORK_PLUGIN_INFO.get(model_name, {}) context["framework_info"] = framework_info # and store return ( diff --git a/pyproject.toml b/pyproject.toml index 39e96ac0..2b83d87c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,14 +20,14 @@ exclude = [ ".venv", "**/migrations/**", ] -ignore = [ +lint.ignore = [ "E501", # line too long "F403", # 'from module import *' used; unable to detect undefined names "E701", # multiple statements on one line (colon) "F401", # module imported but unused ] line-length = 119 -select = [ +lint.select = [ "I", "E", "F", diff --git a/tests/link/test_urlconf.py b/tests/link/test_urlconf.py index a7d4d408..b90454ce 100644 --- a/tests/link/test_urlconf.py +++ b/tests/link/test_urlconf.py @@ -1,10 +1,9 @@ from unittest import skipIf from cms.test_utils.testcases import CMSTestCase -from cms.utils.apphook_reload import reload_urlconf -from django.urls import NoReverseMatch, reverse +from cms.utils.urlutils import admin_reverse +from django.urls import NoReverseMatch -from djangocms_frontend.contrib.link.forms import LinkForm from tests.fixtures import DJANGO_CMS4, TestFixture @@ -12,24 +11,6 @@ class TestUrlConfTestCase(TestFixture, CMSTestCase): def test_select2_url_reversible(self): try: - reverse("dcf_autocomplete:ac_view") - except NoReverseMatch as e: - self.fail(str(e)) - - def test_select2_url_robust_after_url_reload(self): - # reload url but do not execute AppConfig.ready() where - reload_urlconf() - - # Check url is gone - with self.assertRaises(NoReverseMatch): - reverse("dcf_autocomplete:ac_view") - - form = LinkForm() - form.request = None - str(form) # renders form - - # Now does not fail - try: - reverse("dcf_autocomplete:ac_view") + admin_reverse("link_link_autocomplete") except NoReverseMatch as e: self.fail(str(e))