예제 #1
0
    def __init__(self, disable=None, enable=None, html_field_name=None,
                 on_change=False, *args, **kwargs):
        self._html_field_name = html_field_name
        self._markdown = Markdown(disable=disable, enable=enable)
        self._on_change = on_change

        super(MarkdownField, self).__init__(*args, **kwargs)
예제 #2
0
class MarkdownField(models.TextField):
    """Stores markdown, converted to HTML and stored in another field on save.

    By default, the resulting HTML is stored in the field whose name is given
    by appending "_html" to this field's name. This can be changed by passing
    an ``html_field_name`` argument to the field's constructor.

    The markdown is converted to HTML on every save unless the constructor's
    ``on_change`` argument is ``True``. This causes a database query to be
    performed on save to determine if any changes have been made.

    With ``politics.utils.feature_markdown`` used to perform the conversion,
    certain markdown features (e.g. images) can be enabled or disabled using
    the keyword arguments of the same name. To disable images, for example:

    .. code-block:: python

        description = MarkdownField(disable=["images"])
        description_html = models.TextField()

    :param         disable: Markdown features that are to be disabled.
    :type          disable: *Iterable* or ``None``
    :param          enable: Markdown features that are to be enabled.
    :type           enable: *Iterable* or ``None``
    :param html_field_name: The name of the field in which the HTML will be
                            stored. If ``None``, this field's name plus "_html".
    :type  html_field_name: ``None`` or ``str``
    :param       on_change: If ``True``, the conversion will only be performed
                            if changes are detected. Requires a database query.
    :type        on_change: ``bool``
    """

    def __init__(self, disable=None, enable=None, html_field_name=None,
                 on_change=False, *args, **kwargs):
        self._html_field_name = html_field_name
        self._markdown = Markdown(disable=disable, enable=enable)
        self._on_change = on_change

        super(MarkdownField, self).__init__(*args, **kwargs)

    def contribute_to_class(self, cls, name):
        # Determine the HTML field's name.
        if getattr(self, "_html_field_name", None) is None:
            self._html_field_name = "{0}_html".format(name)

        super(MarkdownField, self).contribute_to_class(cls, name)

    def pre_save(self, model_instance, add):
        value = getattr(model_instance, self.attname)

        # We can't detect changes if the model instance is new.
        if self._on_change and not add:
            model = model_instance.__class__
            old_model_instance = model.objects.get(pk=model_instance.pk)

            # If the value hasn't changed, don't perform the conversion.
            if value == getattr(old_model_instance, self.attname):
                return value

        # Convert the markdown to HTML, store it.
        result = self._markdown.convert(value)
        setattr(model_instance, self._html_field_name, result)

        return value