SaltyCrane Blog — Notes on JavaScript and web development

Django Blog Project #13: Updating Django 1.0 Beta 2 New Comments and Adding Markdown support

I've updated to Django 1.0 Beta 2. One of the big items for this release was the new commenting framework. I had been waiting for this, so I was excited to see it was finally done.

I also added support for Markdown formatting of my comments. I actually could have added this earlier, but I only recently learned that Django has built-in support for Markdown.

Update URLConf

When I glanced over the changes for the new commenting framework, I missed this change and I actually had to Google on my error message. Luckily, someone (I don't remember where I found it now) had run into the same problem and saved me.

~/src/django/myblogsite/urls.py:
--- a/urls.py   Thu Aug 21 10:05:20 2008 -0500
+++ b/urls.py   Mon Sep 01 22:34:16 2008 -0700
@@ -1,6 +1,6 @@
 from django.conf.urls.defaults import *
 from django.contrib import admin
-from django.contrib.comments.models import FreeComment
+from django.contrib.comments.models import Comment
 from iwiwdsmi.myblogapp.views import *
 from iwiwdsmi.feeds import *
 from iwiwdsmi.views import *
@@ -19,7 +19,7 @@
     (r'^admin/(.*)', admin.site.root),
     (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', 
      {'feed_dict': feeds}),
-    (r'^comments/', include('django.contrib.comments.urls.comments')),
+    (r'^comments/', include('django.contrib.comments.urls')),
     
     (r'^$', rootview),</url>
Update the database

See the Django Upgrading from Django's previous comment system guide for more complete information.

  • I ran
    $ cd ~/src/django/myblogsite
    $ python manage.py syncdb
  • Then I entered my sqlite3 shell:
    $ sqlite3 mydatabase.sqlite3
    and pasted the following at the command prompt:
    BEGIN;
    
    INSERT INTO django_comments
        (content_type_id, object_pk, site_id, user_name, user_email, user_url,
        comment, submit_date, ip_address, is_public, is_removed)
    SELECT
        content_type_id, object_id, site_id, person_name, '', '', comment,
        submit_date, ip_address, is_public, approved
    FROM comments_freecomment;
    
    INSERT INTO django_comments
        (content_type_id, object_pk, site_id, user_id, user_name, user_email,
        user_url, comment, submit_date, ip_address, is_public, is_removed)
    SELECT
        content_type_id, object_id, site_id, user_id, '', '', '', comment,
        submit_date, ip_address, is_public, is_removed
    FROM comments_comment;
    
    UPDATE django_comments SET user_name = (
        SELECT username FROM auth_user
        WHERE django_comments.user_id = auth_user.id
    ) WHERE django_comments.user_id is not NULL;
    UPDATE django_comments SET user_email = (
        SELECT email FROM auth_user
        WHERE django_comments.user_id = auth_user.id
    ) WHERE django_comments.user_id is not NULL;
    
    COMMIT;
    then exited:
    .exit
Templates

The rest of the changes were with the templates.

  • I removed my old comments templates:
    rm -rf ~/src/django/myblogsite/templates/comments
  • I copied the new templates:
    cp -r ~/lib/django_trunk/django/contrib/comments ~/src/django/myblogsite/templates
  • I updated ~/src/django/myblogsite/templates/listpage.html:
    --- a/templates/listpage.html   Thu Aug 21 10:05:20 2008 -0500
    +++ b/templates/listpage.html   Mon Sep 01 22:46:34 2008 -0700
    @@ -47,7 +47,7 @@
           {% endfor %}
           &nbsp;&nbsp;|&nbsp;&nbsp;
     
    -      {% get_free_comment_count for myblogapp.post post.id as comment_count %}
    +      {% get_comment_count for myblogapp.post post.id as comment_count %}
           <a href="{{ post.get_absolute_url }}#comments">
             {{ comment_count|add:post.lc_count }} 
             Comment{{ comment_count|add:post.lc_count|pluralize}}</a>
    
  • I updated ~/src/django/myblogsite/templates/singlepost.html:
    --- a/templates/singlepost.html Thu Aug 21 10:05:20 2008 -0500
    +++ b/templates/singlepost.html Tue Sep 02 00:44:51 2008 -0700
    @@ -1,6 +1,7 @@
     {% extends "base.html" %}
     
     {% load comments %}
    +{% load markup %}
     
     {% block title %}
       {{ main_title }}: {{ post.title }}
    @@ -59,8 +60,8 @@
       {% endfor %}
       <br />
     
    -  {% get_free_comment_list for myblogapp.post post.id as comment_list %}
    -  {% get_free_comment_count for myblogapp.post post.id as comment_count %}
    +  {% get_comment_list for myblogapp.post post.id as comment_list %}
    +  {% get_comment_count for myblogapp.post post.id as comment_count %}
       {% if comment_list %}
         <h4>{{ comment_count }} 
         {% if lc_list %}New {% endif %}
    @@ -69,13 +70,19 @@
       {% for comment in comment_list %}
         <br />
         <a name="c{{ comment.id }}" href="#c{{ comment.id }}">#{{ forloop.counter }}</a>
    -    <b>{{ comment.person_name|escape }}</b> commented, 
    -      on {{ comment.submit_date|date:"F j, Y" }} at {{ comment.submit_date|date:"P" }}:
    -    {{ comment.comment|escape|urlizetrunc:40|linebreaks }}
    +    <b>
    +      {% if comment.url %}
    +        <a href="{{ comment.url }}">{{ comment.name|escape }}</a>
    +      {% else %}
    +        {{ comment.name|escape }}
    +      {% endif %}
    +    </b> commented, 
    +    on {{ comment.submit_date|date:"F j, Y" }} at {{ comment.submit_date|date:"P" }}:
    +    {{ comment.comment|markdown:"safe" }}
       {% endfor %}
       <br />
     
       </h4><h4>Post a comment</h4>
    -  {% free_comment_form for myblogapp.post post.id %}
    +  {% render_comment_form for post %}
     
     {% endblock %}
    
Add django.contrib.markup to INSTALLED_APPS

To use Markdown, I added django.contrib.markup to my INSTALLED_APPS in settings.py ~/src/django/myblogsite/settings.py:

 INSTALLED_APPS = (
     'django.contrib.auth',
     'django.contrib.contenttypes',
     'django.contrib.sessions',
     'django.contrib.sites',
     'django.contrib.admin',
     'django.contrib.comments',
+    'django.contrib.markup',
     'iwiwdsmi.myblogapp',
 )

That was about it. I messed with the templates a little to try to make things a little prettier. I'm not completely satisfied yet though. My next step is to add django-openid support. Later on, I'd also like to add email notification and spam filtering.

Error messages:
got an unexpected keyword argument 'core'
Validating models...
Unhandled exception in thread started by 
Traceback (most recent call last):
  File "/home/sofeng/lib/python-packages/django/core/management/commands/runserver.py", line 47, in inner_run
    self.validate(display_num_errors=True)
  File "/home/sofeng/lib/python-packages/django/core/management/base.py", line 122, in validate
    num_errors = get_validation_errors(s, app)
  File "/home/sofeng/lib/python-packages/django/core/management/validation.py", line 28, in get_validation_errors
    for (app_name, error) in get_app_errors().items():
  File "/home/sofeng/lib/python-packages/django/db/models/loading.py", line 128, in get_app_errors  
    self._populate()
  File "/home/sofeng/lib/python-packages/django/db/models/loading.py", line 57, in _populate
    self.load_app(app_name, True)
  File "/home/sofeng/lib/python-packages/django/db/models/loading.py", line 72, in load_app
    mod = __import__(app_name, {}, {}, ['models'])
  File "/home/sofeng/src/django/mozblog/myblogapp/models.py", line 30, in 
    class LegacyComment(models.Model):
  File "/home/sofeng/src/django/mozblog/myblogapp/models.py", line 32, in LegacyComment
    website = models.URLField(core=False)
  File "/home/sofeng/lib/python-packages/django/db/models/fields/__init__.py", line 828, in __init__
    CharField.__init__(self, verbose_name, name, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'core'

I removed the core argument from my models. This is an oldforms related thing that has been removed. See here

Error while importing URLconf myblogsite.urls': cannot import name FreeComment

Comments have been refactored. See the Upgrading Guide