Learn how to export your Isso comments to Disqus using this simple Python script

I’ve been using Isso since I launched this blog and it’s been working very well but I still much prefer the Disqus experience.

I didn’t find anything on the web about migrating from Isso to Disqus, which is to be expected. So I made my own tool, and I’m happy to report it works!

Isso stores comments in an SQLite database. To import our comments on Disqus, we will have to somehow generate a XML file that matches their custom XML format, which is based on the WXR (WordPress eXtended RSS) schema.

Fortunately, their giving us a sample of this XML format. My idea was the following: access the Isso database with an ORM and generate the export by using a templating engine.

Unsurprisingly I settled on Python for a quick and dirty script, available on Github at angristan/isso-to-disqus. The usage instructions are in the README, but it’s as simple as:

export WEBSITE_URL=https://blog.tld DB_FILE_PATH=comments.db
python isso-to-disqus.py

I used peewee, a light ORM that supports SQLite, and Jinja2 as a templating engine, since I’m an Ansible user.

After copying a copy of the Isso database, I started writing the models matching the SQL schema, and leaving out the columns I didn’t need.

class Threads(BaseModel):
    uri = CharField()
    title = CharField()

class Comments(BaseModel):
    thread = ForeignKeyField(Threads, backref='comments')
    parent = IntegerField()
    created = FloatField()
    remote_addr = CharField()
    text = CharField()
    author = CharField()
    email = CharField()
    website = CharField()

I had to add a migrating step to rename a column because a foreign key wasn’t working.

migrator = SqliteMigrator(db)
        migrator.rename_column('comments', 'tid', 'thread_id'),

Then I noticed the title column in the threads table was empty. Since I seem to need it for the disqus import, I wrote an extra step that iterates over each thread URL (=blog post) and get the title with Beautiful Soup to fill the database.

threads = Threads.select()

for thread in threads:
    soup = BeautifulSoup(urlopen(os.environ.get('WEBSITE_URL') + thread.uri),features="html5lib")
    thread.title = soup.title.string

That being done, I just had to select all the comments from my database and fill the Jinja template with them. The Jinja template then iterates over each comment and create the XML file.

comments = Comments.select()

template = env.get_template('template.xml.j2')
output = template.render(comments=comments,website_url=os.environ.get('WEBSITE_URL'))

with open("export.xml", "w") as fh:

Once that was done, I created a new Disqus forum and imported the XML file. To see the import status and possible errors, I recommend going to import.disqus.com. To make sure I had a clean state after a few failures, I recreated the forum and imported the 100% valid XML file.

Sadly, I can’t assign my own comments to my own account even though they match my email address and I’m the admin of the forum… Too bad.

The final step was to replace Isso with Disqus on the front-end. I just had to update my Ghost theme by using the snippet given by Disqus, and do some CSS adjustments.

Now, everything looks clean I have a fully featured (but 3rd party) commenting system. Until Ghost has native comments, I guess.

Edit: Well, I changed my mind and went back to Isso. This might still help someone so I’m keeping the post up…