예제 #1
0
class MarkupItem(ContentItem):
    """
    A snippet of markup (restructuredtext, markdown, or textile) to display at a page.
    """

    text = models.TextField(_("markup"))

    # Store the language to keep rendering intact while switching settings.
    language = models.CharField(
        _("Language"),
        max_length=30,
        editable=False,
        db_index=True,
        choices=backend.LANGUAGE_CHOICES,
    )

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    class Meta:
        verbose_name = _("Markup code")
        verbose_name_plural = _("Markup code")

    def __str__(self):
        return Truncator(self.text).words(20)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Extra polymorphic, in case the base class content ID was stored.
        ProxyModelClass = LANGUAGE_MODEL_CLASSES.get(self.language, None)
        if ProxyModelClass:
            self.__class__ = ProxyModelClass
예제 #2
0
class GistItem(ContentItem):
    """
    A reference to a gist item (gist.github.com) that is rendered as source code.
    """
    gist_id = models.CharField(
        _("Gist number"),
        max_length=128,
        help_text=
        _('Go to <a href="https://gist.github.com/" target="_blank">https://gist.github.com/</a> and copy the number of the Gist snippet you want to display.'
          ))
    filename = models.CharField(
        _("Gist filename"),
        max_length=128,
        blank=True,
        help_text=_(
            'Leave the filename empty to display all files in the Gist.'))

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    class Meta:
        verbose_name = _('GitHub Gist snippet')
        verbose_name_plural = _('GitHub Gist snippets')

    def __str__(self):
        return str(self.gist_id)
예제 #3
0
class TwitterRecentEntriesItem(ContentItem):
    """
    Content item to display recent entries of a twitter user.
    """
    title = models.CharField(
        _('Title'),
        max_length=200,
        blank=True,
        help_text=_(
            'You may use Twitter markup here, such as a #hashtag or @username.'
        ))

    twitter_user = models.CharField(_('Twitter user'), max_length=75)
    amount = models.PositiveSmallIntegerField(_('Number of results'),
                                              default=5)

    footer_text = models.CharField(
        _('Footer text'),
        max_length=200,
        blank=True,
        help_text=_(
            'You may use Twitter markup here, such as a #hashtag or @username.'
        ))
    include_retweets = models.BooleanField(_("Include retweets"),
                                           default=False)
    include_replies = models.BooleanField(_("Include replies"), default=False)

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    def __str__(self):
        return self.title or self.twitter_user

    class Meta:
        verbose_name = _('Recent twitter entries')
        verbose_name_plural = _('Recent twitter entries')
예제 #4
0
class GoogleDocsViewerItem(ContentItem):
    """
    A Google Docs viewer that is displayed at the page.
    """
    url = models.URLField(
        _("File URL"),
        help_text=
        _("Specify the URL of an online document, for example a PDF or DOCX file."
          ))
    width = models.CharField(
        _("Width"),
        max_length=10,
        validators=[validate_html_size],
        default="100%",
        help_text=
        _("Specify the size in pixels, or a percentage of the container area size."
          ))
    height = models.CharField(_("Height"),
                              max_length=10,
                              validators=[validate_html_size],
                              default="600",
                              help_text=_("Specify the size in pixels."))

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    class Meta:
        verbose_name = _("Embedded document")
        verbose_name_plural = _("Embedded document")

    def __str__(self):
        return self.url
class TextItem(ContentItem):
    """
    A snippet of HTML text to display on a page.
    """

    text = PluginHtmlField(_("text"), blank=True)
    text_final = models.TextField(editable=False, blank=True, null=True)

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    class Meta:
        verbose_name = _("Text")
        verbose_name_plural = _("Text")

    def __str__(self):
        return Truncator(strip_tags(self.text)).words(20)

    def full_clean(self, *args, **kwargs):
        # This is called by the form when all values are assigned.
        # The pre filters are applied here, so any errors also appear as ValidationError.
        super().full_clean(*args, **kwargs)

        self.text, self.text_final = apply_filters(self,
                                                   self.text,
                                                   field_name="text")
        if self.text_final == self.text:
            # No need to store duplicate content:
            self.text_final = None
예제 #6
0
class IframeItem(ContentItem):
    """
    An ``<iframe>`` that is displayed at the page..
    """

    src = models.URLField(_("Page URL"))
    width = models.CharField(
        _("Width"),
        max_length=10,
        validators=[validate_html_size],
        default="100%",
        help_text=_(
            "Specify the size in pixels, or a percentage of the container area size."
        ),
    )
    height = models.CharField(
        _("Height"),
        max_length=10,
        validators=[validate_html_size],
        default="600",
        help_text=_("Specify the size in pixels."),
    )

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    class Meta:
        verbose_name = _("Iframe")
        verbose_name_plural = _("Iframes")

    def __str__(self):
        return self.src
class OEmbedItem(AbstractOEmbedItem):
    """
    Embedded media via OEmbed
    """

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    class Meta:
        verbose_name = _("Online media")
        verbose_name_plural = _("Online media")
예제 #8
0
class FormDesignerLink(ContentItem):
    form_definition = models.ForeignKey(FormDefinition, verbose_name=_('Form'))

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    class Meta:
        verbose_name = _('Form link')
        verbose_name_plural = _('Form links')

    def __str__(self):
        return self.form_definition.title if self.form_definition else u''
예제 #9
0
class DisqusCommentsAreaItem(ContentItem):
    allow_new = models.BooleanField(_("Allow posting new comments"), default=True)

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    class Meta:
        verbose_name = _('Disqus comments area')
        verbose_name_plural = _('Disqus comments areas')

    def __str__(self):
        return u''
예제 #10
0
class FormDesignerLink(ContentItem):
    form_definition = models.ForeignKey(FormDefinition,
                                        on_delete=models.PROTECT,
                                        verbose_name=_("Form"))

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    class Meta:
        verbose_name = _("Form link")
        verbose_name_plural = _("Form links")

    def __str__(self):
        return self.form_definition.title if self.form_definition else ""
예제 #11
0
class ArticleTextItem(ContentItem):
    """
    This model can be placed on every placeholder field / page.
    """
    text = models.TextField("Text")

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    class Meta:
        verbose_name = "Article text item"
        verbose_name_plural = "Article text items"

    def __str__(self):
        return self.text
예제 #12
0
class SharedContentItem(ContentItem):
    """
    The contentitem to include in a page.
    """
    shared_content = models.ForeignKey(SharedContent, on_delete=models.CASCADE, verbose_name=_('Shared content'), related_name='shared_content_items')

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    class Meta:
        verbose_name = _('Shared content')
        verbose_name_plural = _('Shared content')

    def __str__(self):
        return str(self.shared_content)
예제 #13
0
class RawHtmlItem(ContentItem):
    html = models.TextField(
        _('HTML code'),
        help_text=
        _("Enter the HTML code to display, like the embed code of an online widget."
          ))

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    class Meta:
        verbose_name = _('HTML code')
        verbose_name_plural = _('HTML code')

    def __str__(self):
        return strip_tags(self.html).strip()
예제 #14
0
class PictureItem(ContentItem):
    """
    Display a picture
    """

    ALIGN_LEFT = "left"
    ALIGN_CENTER = "center"
    ALIGN_RIGHT = "right"
    ALIGN_CHOICES = (
        (ALIGN_LEFT, _("Left")),
        (ALIGN_CENTER, _("Center")),
        (ALIGN_RIGHT, _("Right")),
    )

    image = PluginImageField(_("Image"),
                             upload_to=appsettings.FLUENT_PICTURE_UPLOAD_TO)
    caption = models.TextField(_("Caption"), blank=True)
    align = models.CharField(_("Align"),
                             max_length=10,
                             choices=ALIGN_CHOICES,
                             blank=True)
    url = PluginUrlField(_("URL"), blank=True)
    in_new_window = models.BooleanField(_("Open in a new window"),
                                        default=False,
                                        blank=True)

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    class Meta:
        verbose_name = _("Picture")
        verbose_name_plural = _("Pictures")

    def __str__(self):
        return self.caption or str(self.image)

    @property
    def align_class(self):
        """
        The CSS class for alignment.
        """
        if self.align == self.ALIGN_LEFT:
            return "align-left"
        elif self.align == self.ALIGN_CENTER:
            return "align-center"
        elif self.align == self.ALIGN_RIGHT:
            return "align-right"
        else:
            return ""
예제 #15
0
class TwitterSearchItem(ContentItem):
    """
    Content item to display recent entries of a twitter user.
    """

    title = models.CharField(
        _("Title"),
        max_length=200,
        blank=True,
        help_text=_(
            "You may use Twitter markup here, such as a #hashtag or @username."
        ),
    )

    query = models.CharField(
        _("Search for"),
        max_length=200,
        default="",
        help_text=
        _('<a href="https://support.twitter.com/articles/71577" target="_blank">Twitter search syntax</a> is allowed.'
          ),
    )
    amount = models.PositiveSmallIntegerField(_("Number of results"),
                                              default=5)

    footer_text = models.CharField(
        _("Footer text"),
        max_length=200,
        blank=True,
        help_text=_(
            "You may use Twitter markup here, such as a #hashtag or @username."
        ),
    )
    include_retweets = models.BooleanField(_("Include retweets"),
                                           default=False)
    include_replies = models.BooleanField(_("Include replies"), default=False)

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    def __str__(self):
        return self.title or self.query

    class Meta:
        verbose_name = _("Twitter search feed")
        verbose_name_plural = _("Twitter search feed")
예제 #16
0
class CodeItem(ContentItem):
    """
    A snippet of source code, formatted with syntax highlighting.
    """

    language = HideChoicesCharField(
        _('Language'),
        max_length=50,
        choices=backend.LANGUAGE_CHOICES,
        default=appsettings.FLUENT_CODE_DEFAULT_LANGUAGE)
    code = models.TextField(_('Code'))
    linenumbers = models.BooleanField(
        _('Show line numbers'),
        default=appsettings.FLUENT_CODE_DEFAULT_LINE_NUMBERS)

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    class Meta:
        verbose_name = _('Code snippet')
        verbose_name_plural = _('Code snippets')

    def __str__(self):
        return Truncator(self.code).words(20)
예제 #17
0
class AbstractOEmbedItem(ContentItem):
    """
    The base class for an OEmbedItem,
    This allows to create custom models easily.

    .. versionadded:: 1.0
    """

    TYPE_PHOTO = "photo"
    TYPE_VIDEO = "video"
    TYPE_RICH = "rich"  # HTML
    TYPE_LINK = "link"

    # Fetch parameters
    embed_url = OEmbedUrlField(_("URL to embed"))
    embed_max_width = models.PositiveIntegerField(_("Max width"),
                                                  blank=True,
                                                  null=True)
    embed_max_height = models.PositiveIntegerField(_("Max height"),
                                                   blank=True,
                                                   null=True)

    # The cached response:
    type = models.CharField(editable=False,
                            max_length=20,
                            null=True,
                            blank=True)
    url = models.URLField(editable=False, null=True, blank=True)
    title = models.CharField(editable=False,
                             max_length=512,
                             null=True,
                             blank=True)
    description = models.TextField(editable=False, null=True, blank=True)

    author_name = models.CharField(editable=False,
                                   max_length=255,
                                   null=True,
                                   blank=True)
    author_url = models.URLField(editable=False, null=True, blank=True)
    provider_name = models.CharField(editable=False,
                                     max_length=255,
                                     null=True,
                                     blank=True)
    provider_url = models.URLField(editable=False, null=True, blank=True)

    thumbnail_url = models.URLField(editable=False, null=True, blank=True)
    thumbnail_height = models.IntegerField(editable=False,
                                           null=True,
                                           blank=True)
    thumbnail_width = models.IntegerField(editable=False,
                                          null=True,
                                          blank=True)

    height = models.IntegerField(editable=False, null=True, blank=True)
    width = models.IntegerField(editable=False, null=True, blank=True)
    html = models.TextField(editable=False, null=True, blank=True)

    objects = ContentItemManager()  # Avoid Django 1.10 migrations

    class Meta:
        abstract = True
        verbose_name = _("Online media")
        verbose_name_plural = _("Online media")

    def __str__(self):
        return self.title or self.embed_url

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._old_embed_url = self.embed_url
        self._old_embed_max_width = self.embed_max_width
        self._old_embed_max_height = self.embed_max_height

    def save(self, *args, **kwargs):
        self.update_oembed_data(
        )  # if clean() did not run, still update the oembed
        super().save(*args, **kwargs)

    def clean(self):
        # Avoid getting server errors when the URL is not valid.
        try:
            self.update_oembed_data()
        except ProviderException as e:
            raise ValidationError(str(e))

    def update_oembed_data(self, force=False, **backend_params):
        """
        Update the OEmbeddata if needed.

        .. versionadded:: 1.0 Added force and backend_params parameters.
        """
        if appsettings.FLUENT_OEMBED_FORCE_HTTPS and self.embed_url.startswith(
                "http://"):
            self.embed_url = "https://" + self.embed_url[7:]

        if force or self._input_changed():
            # Fetch new embed code
            params = self.get_oembed_params(self.embed_url)
            params.update(backend_params)
            response = backend.get_oembed_data(self.embed_url, **params)

            # Save it
            self.store_response(response)

            # Track field changes
            self._old_embed_url = self.embed_url
            self._old_embed_max_width = self.embed_max_width
            self._old_embed_max_height = self.embed_max_height

    def get_oembed_params(self, embed_url):
        """
        .. versionadded:: 1.0

           Allow to define the parameters that are passed to the backend to fetch the current URL.
        """
        return {
            "maxwidth": self.embed_max_width,
            "maxheight": self.embed_max_height
        }

    def _input_changed(self):
        return (not self.type or self._old_embed_url != self.embed_url
                or self._old_embed_max_width != self.embed_max_width
                or self._old_embed_max_height != self.embed_max_height)

    def store_response(self, response):
        # Store the OEmbed response
        # Unused: cache_age
        # Security considerations: URLs are checked by Django for http:// or ftp://
        KEYS = (
            "type",
            "title",
            "description",
            "author_name",
            "author_url",
            "provider_url",
            "provider_name",
            "thumbnail_width",
            "thumbnail_height",
            "thumbnail_url",
            "height",
            "width",
            "html",
            "url",
        )

        for key in KEYS:
            if key in response:
                setattr(self, key, response[key])