예제 #1
0
class BaseWizardForm(BaseFormMixin, forms.Form):
    """
    Factorize the part of the wizard form that handles the title and the slug as they are
    common to all our wizard forms.
    """

    title = forms.CharField(
        max_length=255,
        required=True,
        widget=forms.TextInput(),
        label=_("Page title"),
        help_text=_("Title of the page in current language"),
    )
    slug = forms.CharField(
        max_length=
        200,  # Should be less than 255, the "max_length" of a Page's "path" field
        required=False,
        widget=SlugWidget(),
        validators=[validators.validate_slug],
        label=_("Page slug"),
        help_text=_("Slug of the page in current language"),
    )

    def clean(self):
        """
        Ensure that the slug field is set or derive it from the title
        """
        cleaned_data = super().clean()

        # If the slug is not explicitly set, generate it from the title
        if cleaned_data.get("title") and not cleaned_data.get("slug"):
            cleaned_data["slug"] = slugify(cleaned_data["title"])[:200]

        # Check that the length of the slug is compatible with its parent page:
        #  a page `path` is limited to 255 chars, therefore the course page slug should
        # always be shorter than (255 - length of parent page path - 1 character for the "/")
        length = len(self.parent_page.get_path()) + 1 + len(
            cleaned_data["slug"])
        if length > 255:
            raise forms.ValidationError({
                "slug": [
                    _("This slug is too long. The length of the path built by "
                      "prepending the slug of the parent page would be {:d} characters "
                      "long and it should be less than 255".format(length))
                ]
            })

        if (self.parent_page.get_child_pages().filter(
                title_set__slug=cleaned_data["slug"]).exists()):
            raise forms.ValidationError(
                {"slug": [_("This slug is already in use")]})

        return cleaned_data

    @cached_property
    def parent_page(self):
        """
        The parent page for each type of page is defined on its page extension model.
        """
        try:
            return Page.objects.get(reverse_id=self.model.PAGE["reverse_id"],
                                    publisher_is_draft=True)
        except Page.DoesNotExist as error:
            raise forms.ValidationError({
                "slug": [
                    _("You must first create a parent page and set its `reverse_id` to "
                      "`{reverse}`.".format(
                          reverse=self.model.PAGE["reverse_id"]))
                ]
            }) from error

    def save(self):
        """
        Create the page with "title" and "slug"
        """
        return create_page(
            title=self.cleaned_data["title"],
            slug=self.cleaned_data["slug"],
            language=get_language(),
            parent=self.parent_page,
            template=self.model.PAGE["template"],
            published=False,  # The creation wizard should not publish the page
        )
예제 #2
0
class BaseWizardForm(forms.Form):
    """
    Factorize the part of the wizard form that handles the title and the slug as they are
    common to all our wizard forms.
    """

    title = forms.CharField(
        max_length=255,
        required=True,
        widget=forms.TextInput(),
        label=_("Page title"),
        help_text=_("Title of the page in current language"),
    )
    slug = forms.CharField(
        max_length=200,  # Should be less than 255, the "max_length" of a Page's "path" field
        required=False,
        widget=SlugWidget(),
        label=_("Page slug"),
        help_text=_("Slug of the page in current language"),
    )

    def clean(self):
        """
        Ensure that the slug field is set or derive it from the title
        """
        cleaned_data = super().clean()
        # If the slug is not explicitly set, generate it from the title
        if cleaned_data.get("title") and not cleaned_data.get("slug"):
            cleaned_data["slug"] = slugify(cleaned_data["title"])[:200]

        return cleaned_data

    def clean_slug(self):
        """
        First check that a parent page exists under which we can create the new page,
        then check that the length of the slug is compatible with this parent page:
        a page `path` is limited to 255 chars, therefore the course page slug should
        always be shorter than (255 - length of parent page path - 1 character for the "/")
        """
        # pylint: disable=no-member
        parent_page = Page.objects.filter(
            reverse_id=self.model.ROOT_REVERSE_ID, publisher_is_draft=True
        ).first()
        if not parent_page:
            raise forms.ValidationError(
                _(
                    "You must first create a parent page and set its `reverse_id` to "
                    "`{reverse}`.".format(reverse=self.model.ROOT_REVERSE_ID)
                )
            )
        total_size = len(parent_page.get_slug()) + 1 + len(self.cleaned_data["slug"])
        if total_size > 255:
            raise forms.ValidationError(
                _(
                    "This slug is too long. The length of the path built by prepending the slug "
                    "of the parent page would be {:d} characters long and it should be less "
                    "than 255".format(total_size)
                )
            )
        return self.cleaned_data["slug"]

    def save(self):
        """
        Create the page with "title" and "slug"
        """
        # We checked in the "clean" method that the parent page exists. Let's retrieve it:
        parent = Page.objects.get(
            reverse_id=self.model.ROOT_REVERSE_ID, publisher_is_draft=True
        )

        # Create the CMS page for the person
        return create_page(
            title=self.cleaned_data["title"],
            slug=self.cleaned_data["slug"],
            language=get_language(),
            parent=parent,
            template=self.model.TEMPLATE_DETAIL,
            published=False,  # The creation wizard should not publish the page
        )