divio/django-cms

View on GitHub
cms/wizards/forms.py

Summary

Maintainability
A
50 mins
Test Coverage
from django import forms

from cms.models import Page
from cms.utils.urlutils import static_with_version

from .wizard_pool import entry_choices, wizard_pool


def step2_form_factory(mixin_cls, entry_form_class, attrs=None):
    """
    Combines a form mixin with a form class, sets attrs to the resulting class.
    This is used to provide a common behavior/logic for all wizard content
    forms.
    """
    if attrs is None:
        attrs = {}

    # class name is hardcoded to be consistent with the step 1 form.
    # this is meant to be used only in the context of the form wizard.
    class_name = 'WizardStep2Form'
    meta_class = type(entry_form_class)
    FormClass = meta_class(class_name, (mixin_cls, entry_form_class), attrs)
    return FormClass


class BaseFormMixin:
    has_separate_optional_fields = False

    def __init__(self, *args, **kwargs):
        self.page = kwargs.pop('wizard_page', None)
        self.user = kwargs.pop('wizard_user', None)
        self.language_code = kwargs.pop('wizard_language')
        super().__init__(*args, **kwargs)

    @property
    def required_fields(self):
        return [f for f in self.visible_fields() if f.field.required]

    @property
    def optional_fields(self):
        return [f for f in self.visible_fields() if not f.field.required]


class WizardOptionWidgets(forms.RadioSelect):
    template_name = 'cms/wizards/wizardoptionwidget.html'

    def create_option(self, name, value, label, selected, index, subindex=None, attrs=None):
        wizard = wizard_pool.get_entry(value)
        attrs.update(wizard.widget_attributes)
        return super().create_option(name, value, label, selected, index, subindex, attrs)


class WizardStep1Form(BaseFormMixin, forms.Form):

    class Media:
        css = {
            'all': (
                static_with_version('cms/css/cms.wizard.css'),
            )
        }
        js = (
            static_with_version('cms/js/dist/bundle.admin.base.min.js'),
            'cms/js/modules/cms.wizards.js',
        )

    page = forms.ModelChoiceField(
        queryset=Page.objects.all(),
        required=False,
        widget=forms.HiddenInput
    )
    language = forms.CharField(widget=forms.HiddenInput)
    entry = forms.ChoiceField(choices=[], widget=WizardOptionWidgets())

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # set the entries here to get an up-to-date list of entries.
        self.fields['entry'].choices = entry_choices(
            user=self.user,
            page=self.page,
        )

    def get_wizard_entries(self):
        for entry in self['entry']:
            wizard = wizard_pool.get_entry(entry.choice_value)
            yield (entry, wizard)


class WizardStep2BaseForm(BaseFormMixin):
    user = None