Code


Version 2 (modified by ubernostrum, 8 years ago) (diff)

--

CookBook - Using Markup Filters in Models

The markup application (django.contrib.markup) is pretty handy for using filters like Textile or Markdown in your templates, but have a slight downside: every time a page is generated, you have to run the markup filter over the text, which may or may not be an acceptable performance hit. You could, if you wanted, just define a _pre_save hook which applies the filter to incoming text so it gets saved to your DB as HTML, but then you're in a pickle if you want to edit it again later. What to do, then?

One solution is found in the Textpattern CMS, which incorporates Textile. Textpattern accepts input in Textile syntax, and then saves two copies: one is the raw input, which is stored for later use when an item is being edited, and the other is the XHTML Textile produces for that input, which is used for actual page display. The idea here is that database columns are cheap, but processing time might not be. And this is easy to do in Django; for example, let's say you have a weblog where you'd like to use Markdown on the entries. You might define your Entry model like so:

import markdown

class Entry(meta.Model):
    title = meta.CharField('Title', maxlength=250)
    pub_date = meta.DateTimeField('Date published', default=meta.LazyDate())
    body = meta.TextField('Entry body', help_text='Use Markdown syntax.')
    body_markdown = meta.TextField('Entry body as HTML', blank=True)

    class META:
        admin = meta.Admin(
            fields = (
                (None, {'fields': ('title', 'pub_date', 'body')}),
            )
        )

    def _pre_save(self):
        self.body_markdown = markdown.markdown(self.body)

Now you've got the same effect: when creating or editing entries in the admin, you'll only see the field which accepts Markdown syntax, but when saving, the body_markdown field will be auto-filled with the corresponding XHTML. Then in your template, you can pull in entry.body_markdown, and save yourself a little processing time.