Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Format blog entry's summary and body with RST. No moar raw HTML!

  • Loading branch information...
commit 48113e03b4587e1853c04ceeb626ebd95fb2c0a4 1 parent 466670b
Julien Phalip authored May 10, 2011
4  django_website/blog/admin.py
... ...
@@ -1,9 +1,11 @@
1 1
 from __future__ import absolute_import
2 2
 
3 3
 from django.contrib import admin
  4
+
4 5
 from .models import Entry
5 6
 
6 7
 admin.site.register(Entry,
7 8
     list_display = ('headline', 'pub_date', 'is_active', 'is_published', 'author'),
8  
-    list_filter = ('is_active',)
  9
+    list_filter = ('is_active',),
  10
+    exclude = ('summary_html', 'body_html'),
9 11
 )
43  django_website/blog/migrations/0004_auto__add_field_entry_summary_html__add_field_entry_body_html.py
... ...
@@ -0,0 +1,43 @@
  1
+# encoding: utf-8
  2
+import datetime
  3
+from south.db import db
  4
+from south.v2 import SchemaMigration
  5
+from django.db import models
  6
+
  7
+class Migration(SchemaMigration):
  8
+
  9
+    def forwards(self, orm):
  10
+        
  11
+        # Adding field 'Entry.summary_html'
  12
+        db.add_column('blog_entries', 'summary_html', self.gf('django.db.models.fields.TextField')(default=''), keep_default=False)
  13
+
  14
+        # Adding field 'Entry.body_html'
  15
+        db.add_column('blog_entries', 'body_html', self.gf('django.db.models.fields.TextField')(default=''), keep_default=False)
  16
+
  17
+
  18
+    def backwards(self, orm):
  19
+        
  20
+        # Deleting field 'Entry.summary_html'
  21
+        db.delete_column('blog_entries', 'summary_html')
  22
+
  23
+        # Deleting field 'Entry.body_html'
  24
+        db.delete_column('blog_entries', 'body_html')
  25
+
  26
+
  27
+    models = {
  28
+        'blog.entry': {
  29
+            'Meta': {'ordering': "('-pub_date',)", 'object_name': 'Entry', 'db_table': "'blog_entries'"},
  30
+            'author': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  31
+            'body': ('django.db.models.fields.TextField', [], {}),
  32
+            'body_html': ('django.db.models.fields.TextField', [], {}),
  33
+            'headline': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
  34
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  35
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  36
+            'pub_date': ('django.db.models.fields.DateTimeField', [], {}),
  37
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
  38
+            'summary': ('django.db.models.fields.TextField', [], {}),
  39
+            'summary_html': ('django.db.models.fields.TextField', [], {})
  40
+        }
  41
+    }
  42
+
  43
+    complete_apps = ['blog']
35  django_website/blog/migrations/0005_copy_entry_summary_and_body_to_html.py
... ...
@@ -0,0 +1,35 @@
  1
+# encoding: utf-8
  2
+import datetime
  3
+from south.db import db
  4
+from south.v2 import DataMigration
  5
+from django.db import models
  6
+
  7
+class Migration(DataMigration):
  8
+
  9
+    def forwards(self, orm):
  10
+        for entry in orm['blog.Entry'].objects.all():
  11
+            entry.summary_html = entry.summary
  12
+            entry.body_html = entry.body
  13
+            entry.save()
  14
+
  15
+    def backwards(self, orm):
  16
+        "Write your backwards methods here."
  17
+
  18
+
  19
+    models = {
  20
+        'blog.entry': {
  21
+            'Meta': {'ordering': "('-pub_date',)", 'object_name': 'Entry', 'db_table': "'blog_entries'"},
  22
+            'author': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  23
+            'body': ('django.db.models.fields.TextField', [], {}),
  24
+            'body_html': ('django.db.models.fields.TextField', [], {}),
  25
+            'headline': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
  26
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  27
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  28
+            'pub_date': ('django.db.models.fields.DateTimeField', [], {}),
  29
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
  30
+            'summary': ('django.db.models.fields.TextField', [], {}),
  31
+            'summary_html': ('django.db.models.fields.TextField', [], {})
  32
+        }
  33
+    }
  34
+
  35
+    complete_apps = ['blog']
38  django_website/blog/migrations/0006_auto__add_field_entry_use_raw_html.py
... ...
@@ -0,0 +1,38 @@
  1
+# encoding: utf-8
  2
+import datetime
  3
+from south.db import db
  4
+from south.v2 import SchemaMigration
  5
+from django.db import models
  6
+
  7
+class Migration(SchemaMigration):
  8
+
  9
+    def forwards(self, orm):
  10
+        
  11
+        # Adding field 'Entry.use_raw_html'
  12
+        db.add_column('blog_entries', 'use_raw_html', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False)
  13
+
  14
+
  15
+    def backwards(self, orm):
  16
+        
  17
+        # Deleting field 'Entry.use_raw_html'
  18
+        db.delete_column('blog_entries', 'use_raw_html')
  19
+
  20
+
  21
+    models = {
  22
+        'blog.entry': {
  23
+            'Meta': {'ordering': "('-pub_date',)", 'object_name': 'Entry', 'db_table': "'blog_entries'"},
  24
+            'author': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  25
+            'body': ('django.db.models.fields.TextField', [], {}),
  26
+            'body_html': ('django.db.models.fields.TextField', [], {}),
  27
+            'headline': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
  28
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  29
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  30
+            'pub_date': ('django.db.models.fields.DateTimeField', [], {}),
  31
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
  32
+            'summary': ('django.db.models.fields.TextField', [], {}),
  33
+            'summary_html': ('django.db.models.fields.TextField', [], {}),
  34
+            'use_raw_html': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
  35
+        }
  36
+    }
  37
+
  38
+    complete_apps = ['blog']
35  django_website/blog/migrations/0007_existing_entries_are_raw_html.py
... ...
@@ -0,0 +1,35 @@
  1
+# encoding: utf-8
  2
+import datetime
  3
+from south.db import db
  4
+from south.v2 import DataMigration
  5
+from django.db import models
  6
+
  7
+class Migration(DataMigration):
  8
+
  9
+    def forwards(self, orm):
  10
+        for entry in orm['blog.Entry'].objects.all():
  11
+            entry.use_raw_html = True
  12
+            entry.save()
  13
+
  14
+    def backwards(self, orm):
  15
+        "Write your backwards methods here."
  16
+
  17
+
  18
+    models = {
  19
+        'blog.entry': {
  20
+            'Meta': {'ordering': "('-pub_date',)", 'object_name': 'Entry', 'db_table': "'blog_entries'"},
  21
+            'author': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
  22
+            'body': ('django.db.models.fields.TextField', [], {}),
  23
+            'body_html': ('django.db.models.fields.TextField', [], {}),
  24
+            'headline': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
  25
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
  26
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
  27
+            'pub_date': ('django.db.models.fields.DateTimeField', [], {}),
  28
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
  29
+            'summary': ('django.db.models.fields.TextField', [], {}),
  30
+            'summary_html': ('django.db.models.fields.TextField', [], {}),
  31
+            'use_raw_html': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
  32
+        }
  33
+    }
  34
+
  35
+    complete_apps = ['blog']
26  django_website/blog/models.py
@@ -5,6 +5,7 @@
5 5
 from django.contrib.sites.models import Site
6 6
 from django.contrib.comments.signals import comment_was_posted
7 7
 from django.utils.encoding import smart_str
  8
+from docutils.core import publish_parts
8 9
 
9 10
 
10 11
 class EntryManager(models.Manager):
@@ -17,9 +18,12 @@ class Entry(models.Model):
17 18
     slug = models.SlugField(unique_for_date='pub_date')
18 19
     is_active = models.BooleanField(help_text="Tick to make the entry live on site (see also the publication date). Note that administrators (like yourself) are allowed to preview inactive content whereas other users and the general public aren't.", default=False)
19 20
     pub_date = models.DateTimeField(help_text='For an entry to be published, it must be active and its publication date must be in the past.')
20  
-    summary = models.TextField(help_text="Use raw HTML.")
21  
-    body = models.TextField(help_text="Use raw HTML.")
  21
+    summary = models.TextField()
  22
+    summary_html = models.TextField(help_text="Use reStructuredText unless specified otherwise")
  23
+    body = models.TextField(help_text="Use reStructuredText unless specified otherwise")
  24
+    body_html = models.TextField()
22 25
     author = models.CharField(max_length=100)
  26
+    use_raw_html = models.BooleanField(help_text="Tick if you prefer to manually enter raw HTML instead of reStructureText formats in the summary and body. This option's main purpose is to cope with old entries that were entirely written in raw HTML.", default=False)
23 27
 
24 28
     objects = EntryManager()
25 29
     
@@ -47,6 +51,24 @@ def comments_enabled(self):
47 51
         delta = datetime.datetime.now() - self.pub_date
48 52
         return delta.days < 60
49 53
 
  54
+    def save(self, *args, **kwargs):
  55
+        if self.use_raw_html:
  56
+            self.summary_html = self.summary
  57
+            self.body_html = self.body
  58
+        else:
  59
+            settings_overrides = {
  60
+                    'doctitle_xform': False,
  61
+                    'initial_header_level': 4,
  62
+                    'id_prefix': 's-',
  63
+                }
  64
+            self.summary_html = publish_parts(source=smart_str(self.summary),
  65
+                                              writer_name="html",
  66
+                                              settings_overrides=settings_overrides)['fragment']
  67
+            self.body_html = publish_parts(source=smart_str(self.body),
  68
+                                           writer_name="html",
  69
+                                           settings_overrides=settings_overrides)['fragment']
  70
+        super(Entry, self).save(*args, **kwargs)
  71
+    
50 72
 def moderate_comment(sender, comment, request, **kwargs):
51 73
     ak = akismet.Akismet(
52 74
         key = settings.AKISMET_API_KEY,
2  django_website/templates/blog/entry_archive.html
@@ -6,7 +6,7 @@
6 6
 
7 7
 {% for object in latest %}
8 8
     <h2><a href="{{ object.get_absolute_url }}">{{ object.headline|safe }}</a></h2>
9  
-    {{ object.body|safe }}
  9
+    {{ object.body_html|safe }}
10 10
     <p class="date small">Posted by <strong>{{ object.author }}</strong> on {{ object.pub_date|date:"F j, Y" }}</p>
11 11
 {% endfor %}
12 12
 
2  django_website/templates/blog/entry_archive_day.html
@@ -9,7 +9,7 @@
9 9
 {% for object in object_list %}
10 10
 <h2><a href="{{ object.get_absolute_url }}">{{ object.headline|safe }}</a></h2>
11 11
 <p class="small date">{{ object.pub_date|date:"F j, Y" }}</p>
12  
-{{ object.body|safe }}
  12
+{{ object.body_html|safe }}
13 13
 
14 14
 {% endfor %}
15 15
 
2  django_website/templates/blog/entry_archive_month.html
@@ -9,7 +9,7 @@
9 9
 {% for object in object_list %}
10 10
 <h2><a href="{{ object.get_absolute_url }}">{{ object.headline|safe }}</a></h2>
11 11
 <p class="small date">{{ object.pub_date|date:"F j, Y" }}</p>
12  
-{{ object.body|safe }}
  12
+{{ object.body_html|safe }}
13 13
 
14 14
 {% endfor %}
15 15
 
2  django_website/templates/blog/entry_detail.html
@@ -5,6 +5,6 @@
5 5
 {% block content %}
6 6
 <h1>{{ object.headline|safe }}</h1>
7 7
 {% if not object.is_published %}<p><strong>Preview mode</strong></p>{% endif %}
8  
-{{ object.body|safe }}
  8
+{{ object.body_html|safe }}
9 9
 <p class="date small">Posted by <strong>{{ object.author }}</strong> on {{ object.pub_date|date:"F j, Y" }}</p>
10 10
 {% endblock %}
2  django_website/templates/blog/entry_snippet.html
... ...
@@ -1,6 +1,6 @@
1 1
 {% for e in entries %}
2 2
     <h3><a href="{{ e.get_absolute_url }}">{{ e.headline }}</a></h3>
3 3
     <p class="date">by <strong>{{ e.author }}</strong> on {{ e.pub_date|date:"M. j, Y" }}</p>
4  
-    {{ e.summary|safe }}
  4
+    {{ e.summary_html|safe }}
5 5
     <p class="more"><a href="{{ e.get_absolute_url }}">Read more</a></p>
6 6
 {% endfor %}

0 notes on commit 48113e0

Please sign in to comment.
Something went wrong with that request. Please try again.