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
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Awesome idea. Great implemented!
#
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.
#
hmmm...this error pops up:
'NoneType' object has no attribute 'strip'
#
Please login first before commenting.