Login

MarkdownTextField

Author:
carljm
Posted:
July 14, 2008
Language:
Python
Version:
.96
Score:
5 (after 5 ratings)

A common pattern in Django is to create a TextField intended for Markdown text (i.e. description) and a companion non-editable TextField for storing the HTML version (i.e. description_html), so the Markdown converter need not be run for every page view.

This snippet is a custom field which encapsulates this pattern in a single field which can automatically create and update its companion HTML field.

Usage:

class MyModel(models.Model):
    description = MarkdownTextField()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from django.db.models import TextField
from markdown import markdown

class MarkdownTextField (TextField):
    """
    A TextField that automatically implements DB-cached Markdown translation.

    Accepts two additional keyword arguments:

    if allow_html is False, Markdown will be called in safe mode,
    which strips raw HTML (default is allow_html = True).

    if html_field_suffix is given, that value will be appended to the
    field name to generate the name of the non-editable HTML cache
    field.  Default value is "_html".

    NOTE: The MarkdownTextField is not able to check whether the model
    defines any other fields with the same name as the HTML field it
    attempts to add - if there are other fields with this name, a
    database duplicate column error will be raised.

    """
    def __init__ (self, *args, **kwargs):
        self._markdown_safe = not kwargs.pop('allow_html', True)
        self._html_field_suffix = kwargs.pop('html_field_suffix', '_html')
        super(MarkdownTextField, self).__init__(*args, **kwargs)

    def contribute_to_class (self, cls, name):
        self._html_field = "%s%s" % (name, self._html_field_suffix)
        TextField(editable=False).contribute_to_class(cls, self._html_field)
        super(MarkdownTextField, self).contribute_to_class(cls, name)

    def pre_save (self, model_instance, add):
        value = getattr(model_instance, self.attname)
        html = markdown(value, safe_mode=self._markdown_safe)
        setattr(model_instance, self._html_field, html)
        return value

    def __unicode__ (self):
        return self.attname

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 2 months ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 2 months, 1 week ago
  3. Serializer factory with Django Rest Framework by julio 9 months, 1 week ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 9 months, 4 weeks ago
  5. Help text hyperlinks by sa2812 10 months, 3 weeks ago

Comments

marvoloe (on July 15, 2008):

Awesome idea. Great implemented!

#

svetlyak (on November 6, 2008):

I belive, that if you don't want to call markdown or any other postprocessor at any page view, then you should use Cache.

Storing additional data in the database is a bad idea, if you want to archieve a performance.

#

artur_mwaigaryan (on March 27, 2013):

hmmm...this error pops up:

'NoneType' object has no attribute 'strip'

#

Please login first before commenting.