I’ve been neglecting my homepage for a while, and as a dynamic site written in Django, it is harder to manage and I just don’t want to spend the same amount of effort anymore to run a page I don’t frequently update.

To remedy this, I decided to throw everything into static files and build the static files when I do deploys of new content instead of dynamically rendering the pages on each request.

The hardest part about this migration was my old blog posts that were not written in markdown and were located in a database that my Django server was attached to. To remedy this I wrote a script to convert Zinnia blog entries into markdown files in Jekyll’s format.

If you would like to migrate your own blog to Jekyll, you can use the Django management command to dump the data into a JSON file and point the script I wrote at it. To get the data out of your DB, from your Django host run, python manage.py dumpdata zinnia --indent=2 > blog_data.json

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/usr/bin/env python3
# convert_zinnia.py - script for parsing zinnia db blob into jekyll posts

import json
import os

import html2text

# open database of zinna posts created from django's dumpdb command
blog_dump_file = 'blog_data.json'
blog_file = open(blog_dump_file)
blog_json = json.loads(blog_file.read())

# go over each item in the dump and create files for zinnia's entries
for item in blog_json:
    if item['model'] == u'zinnia.entry':
        fields = item['fields']

        title = fields['title']
        creation_date = fields['creation_date']
        status = fields['status']
        slug = fields['slug']
        content = fields['content']

        date, time = creation_date.split(' ')
        year, month, day = date.split('-')

        # convert posts from HTML format into markdown for Jekyll
        md_content = html2text.html2text(content)

        if status == 0:
            status_name = 'draft'
        if status == 1:
            status_name = 'unpublished'
        if status == 2:
            status_name = 'published'
        if status == 3:
            status_name = 'other3'

        if status in [0,1]:
            filename = '%s' % (slug)
            os.makedirs('_drafts', exist_ok=True)
            new_file = open('_drafts/%s.markdown' % filename, 'w')

        if status in [2]:
            filename = '%s-%s-%s-%s' % (year,month,day,slug)
            os.makedirs('_posts', exist_ok=True)
            new_file = open('_posts/%s.markdown' % filename, 'w')


        # create the file for the post and save it to either _posts or _drafts
        header = '''---
    layout: post
    title:  "%s"
    categories: blog
    ---

    %s
    ''' % (title, md_content,)
        new_file.write(header)
        new_file.close()

This script creates _posts and a _drafts directory which you then can copy over to your Jekyll installation. Before publishing your content from Django into Jekyll, be sure to inspect the script output and rendering to make sure you are getting the expected out. I had to hand tune the output files but it was definitely easier than the first couple of entries that I copied over by hand.

One last thing to remember and take care of is making sure your old URLs match your new URLS. The Jekyll file name scheme determines the URLs and the blog category in each post header puts it in the right path.