changeset 124:9c18250972d5

Refactored the markdown/smiley logic. Created classes for Markdown and Smilify. No longer call render_to_string() in models.py for various models.
author Brian Neal <bgneal@gmail.com>
date Sat, 14 Nov 2009 04:32:32 +0000
parents 3ae999b0c53b
children 903ae6168071
files gpp/bio/models.py gpp/comments/models.py gpp/core/markup.py gpp/downloads/models.py gpp/forums/models.py gpp/gcalendar/calendar.py gpp/gcalendar/models.py gpp/messages/models.py gpp/smiley/__init__.py gpp/smiley/templatetags/smiley_tags.py
diffstat 10 files changed, 100 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/gpp/bio/models.py	Sun Nov 08 21:15:31 2009 +0000
+++ b/gpp/bio/models.py	Sat Nov 14 04:32:32 2009 +0000
@@ -8,9 +8,11 @@
 from django.db import models
 from django.contrib import auth
 from django.conf import settings
-from django.template.loader import render_to_string
 from django.core.cache import cache
 
+from core.markup import Markdown
+from smiley import Smilify
+
 
 def avatar_file_path_for_user(username, filename):
     return os.path.join(settings.AVATAR_DIR, 'users', username, filename)
@@ -46,10 +48,9 @@
         ordering = ('user__username', )
 
     def save(self, *args, **kwargs):
-        html = render_to_string('bio/markdown.html', {'data': self.profile_text})
-        self.profile_html = html.strip()
-        html = render_to_string('bio/markdown.html', {'data': self.signature})
-        self.signature_html = html.strip()
+        md = Markdown()
+        sm = Smilify()
+        self.profile_html = sm.convert(md.convert(self.profile_text))
+        self.signature_html = sm.convert(md.convert(self.signature))
         super(UserProfile, self).save(*args, **kwargs)
         cache.delete('avatar_' + self.user.username)
-
--- a/gpp/comments/models.py	Sun Nov 08 21:15:31 2009 +0000
+++ b/gpp/comments/models.py	Sat Nov 14 04:32:32 2009 +0000
@@ -6,9 +6,11 @@
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes import generic
 from django.contrib.auth.models import User
-from django.template.loader import render_to_string
 from django.core import urlresolvers
 
+from core.markup import markdown
+from smiley import smilify
+
 
 COMMENT_MAX_LENGTH = getattr(settings, 'COMMENT_MAX_LENGTH', 3000)
 
@@ -51,8 +53,7 @@
         return u'%s: %s...' % (self.user.username, self.comment[:50])
 
     def save(self, force_insert=False, force_update=False):
-        html = render_to_string('comments/markdown.html', {'data': self.comment})
-        self.html = html.strip()
+        self.html = smilify(markdown(self.comment))
         super(Comment, self).save(force_insert, force_update)
 
     def get_absolute_url(self):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/core/markup.py	Sat Nov 14 04:32:32 2009 +0000
@@ -0,0 +1,30 @@
+"""
+This is a thin wrapper around the Markdown class which deals with the
+differences in Markdown versions on the production and development server.
+This code was inspired by the code in 
+django/contrib/markup/templatetags/markup.py.
+Currently, we only have to worry about Markdown 1.6b and 2.0.
+"""
+import markdown as _markdown
+from django.utils.encoding import force_unicode
+
+from smiley.utils import smilify
+
+class Markdown(object):
+
+    def __init__(self, safe_mode='escape'):
+        # Unicode support only in markdown v1.7 or above. Version_info
+        # exists only in markdown v1.6.2rc-2 or above.
+        self.unicode_support = getattr(_markdown, "version_info", None) >= (1, 7)
+        self.md = _markdown.Markdown(safe_mode=safe_mode)
+
+    def convert(self, s):
+        if self.unicode_support:
+            return self.md.convert(force_unicode(s))
+        else:
+            return force_unicode(self.md.convert(s))
+
+
+def markdown(s):
+    md = Markdown()
+    return md.convert(s)
--- a/gpp/downloads/models.py	Sun Nov 08 21:15:31 2009 +0000
+++ b/gpp/downloads/models.py	Sat Nov 14 04:32:32 2009 +0000
@@ -6,9 +6,11 @@
 import datetime
 from django.db import models
 from django.contrib.auth.models import User
-from django.template.loader import render_to_string
 from django.template.defaultfilters import filesizeformat
 
+from core.markup import markdown
+from smiley import smilify
+
 
 class Category(models.Model):
     """Downloads belong to categories."""
@@ -72,8 +74,7 @@
         return ('downloads-details', [str(self.id)])
 
     def save(self, force_insert=False, force_update=False):
-        html = render_to_string('downloads/markdown.html', {'data': self.description})
-        self.html = html.strip()
+        self.html = smilify(markdown(self.description))
         super(Download, self).save(force_insert, force_update)
 
     def vote(self, vote_value):
--- a/gpp/forums/models.py	Sun Nov 08 21:15:31 2009 +0000
+++ b/gpp/forums/models.py	Sat Nov 14 04:32:32 2009 +0000
@@ -6,7 +6,8 @@
 from django.db import models
 from django.db.models import Q
 from django.contrib.auth.models import User, Group
-from django.template.loader import render_to_string
+from core.markup import markdown
+from smiley import smilify
 
 
 POST_EDIT_DELTA = datetime.timedelta(seconds=3)
@@ -251,8 +252,7 @@
         return self.summary()
 
     def save(self, *args, **kwargs):
-        html = render_to_string('forums/post.html', {'data': self.body})
-        self.html = html.strip()
+        self.html = smilify(markdown(self.body))
         super(Post, self).save(*args, **kwargs)
 
     def delete(self, *args, **kwargs):
--- a/gpp/gcalendar/calendar.py	Sun Nov 08 21:15:31 2009 +0000
+++ b/gpp/gcalendar/calendar.py	Sat Nov 14 04:32:32 2009 +0000
@@ -86,8 +86,8 @@
                     error = True
 
             if error:
-                err_msgs.append('%s - (%d) %s' % \
-                        (qs[i].title, code, entry.batch_status.reason))
+                err_msgs.append('%s - (%d) %s' % (
+                    qs[i].what, code, entry.batch_status.reason))
 
         if len(err_msgs) > 0:
             raise CalendarError(', '.join(err_msgs))
--- a/gpp/gcalendar/models.py	Sun Nov 08 21:15:31 2009 +0000
+++ b/gpp/gcalendar/models.py	Sat Nov 14 04:32:32 2009 +0000
@@ -4,7 +4,9 @@
 from django.db import models
 from django.db.models import Q
 from django.contrib.auth.models import User
-from django.template.loader import render_to_string
+
+from core.markup import markdown
+from smiley import smilify
 
 
 class PendingEventManager(models.Manager):
@@ -90,12 +92,9 @@
         ordering = ('-date_submitted', )
 
     def save(self, *args, **kwargs):
-        html = render_to_string('gcalendar/markdown.html', {'data': self.description})
-        self.html = html.strip()
+        self.html = smilify(markdown(self.description))
         super(Event, self).save(*args, **kwargs)
 
     def needs_approval(self):
         return self.status in (self.NEW, self.EDIT_REQ, self.DEL_REQ)
 
-
-# vim: ts=4 sw=4
--- a/gpp/messages/models.py	Sun Nov 08 21:15:31 2009 +0000
+++ b/gpp/messages/models.py	Sat Nov 14 04:32:32 2009 +0000
@@ -4,7 +4,8 @@
 from django.db import models
 from django.db.models import Q
 from django.contrib.auth.models import User
-from django.template.loader import render_to_string
+from core.markup import markdown
+from smiley import smilify
 
 
 class MessageManager(models.Manager):
@@ -62,8 +63,7 @@
     def save(self, force_insert = False, force_update = False):
         if not self.id:
             self.send_date = datetime.datetime.now()
-        html = render_to_string('messages/markdown.html', {'data': self.message})
-        self.html = html.strip()
+        self.html = smilify(markdown(self.message))
         super(Message, self).save(force_insert, force_update)
 
     @models.permalink
--- a/gpp/smiley/__init__.py	Sun Nov 08 21:15:31 2009 +0000
+++ b/gpp/smiley/__init__.py	Sat Nov 14 04:32:32 2009 +0000
@@ -0,0 +1,41 @@
+"""
+Smiley class and function.
+"""
+import re
+
+from django.utils.safestring import SafeData
+from django.utils.html import conditional_escape
+
+from smiley.models import Smiley
+
+
+class Smilify(object):
+    """
+    A class to "smilify" text by replacing text with HTML img tags of smilies.
+    """
+    def __init__(self):
+        self.map = Smiley.objects.get_smiley_map()
+
+    def convert(self, value, autoescape=False):
+        if not autoescape or isinstance(value, SafeData):
+            esc = lambda x: x
+        else:
+            esc = conditional_escape
+
+        words = value.split()
+        for i, word in enumerate(words):
+            if word in self.map:
+                words[i] = self.map[word]
+            else:
+                words[i] = esc(words[i])
+        return u' '.join(words)
+        
+
+def smilify(value, autoescape=False):
+    """
+    A convenience function to "smilify" text by replacing text with HTML
+    img tags of smilies.
+    """
+    s = Smilify()
+    return s.convert(value, autoescape)
+
--- a/gpp/smiley/templatetags/smiley_tags.py	Sun Nov 08 21:15:31 2009 +0000
+++ b/gpp/smiley/templatetags/smiley_tags.py	Sat Nov 14 04:32:32 2009 +0000
@@ -1,37 +1,21 @@
 """
 Template tags for the smiley application. 
 """
-import re
 from django import template
 from django.template.defaultfilters import stringfilter
-from django.utils.html import conditional_escape
 from django.utils.safestring import mark_safe
-from django.utils.safestring import SafeData
 
 from smiley.models import Smiley
 
 register = template.Library()
 
-word_split_re = re.compile(r'(\s+)')
 
 @register.filter
 @stringfilter
 def smilify(value, autoescape=False):
     """A filter to "smilify" text by replacing text with HTML img tags of smilies."""
-    if not autoescape or isinstance(value, SafeData):
-        esc = lambda x: x
-    else:
-        esc = conditional_escape
-
-    smiley_map = Smiley.objects.get_smiley_map()
-
-    words = word_split_re.split(value)
-    for i, word in enumerate(words):
-        if word in smiley_map:
-            words[i] = smiley_map[word]
-        else:
-            words[i] = esc(words[i])
-    return mark_safe(u''.join(words))
+    from smiley import smilify
+    return mark_safe(smilify(value, autoescape))
 smilify.needs_autoescape = True