Blog platform based on Tornado, MongoDB, and Motor. To be used with MarsEdit.
Frontend: Motor-Blog runs in Tornado. It is very fast.
Editing: Motor-Blog has no admin panel, but supports MarsEdit.
Customization: Appearance is completely customizable.
Install MongoDB and run it on the default port on the same machine as Motor-Blog
pip install -r requirements.txt
To migrate from a prior WordPress blog with migrate_from_wordpress.py you'll need Pandoc
mkdir data mongod --dbpath data --logpath data/mongod.log --fork --setParameter textSearchEnabled=true
Copy motor_blog.conf.example to motor_blog.conf, edit it as desired. Start the application:
python server.py --debug --conf=motor_blog.conf --ensure-indexes
I run Motor-Blog on http://emptysquare.net/blog with Nginx at the front and four
Those processes and MongoDB are managed by Supervisor.
I've provided example config files in this repository in
If you have an Nginx version with WebSocket support (1.3.13 or later)
then draft posts will autoreload when you update them from MarsEdit.
python server.py --ensure-indexes at once when first installing Motor-Blog on a production MongoDB server.
(If you see an error when using the search box, "Can't canonicalize query: IndexNotFound text index required for $text query", it means you haven't done this step. In any case, running Motor-Blog without indexes built will risk performance problems.)
In MarsEdit, do "File -> New Blog." Give it a name and the URL of your Motor-Blog's home page. MarsEdit auto-detects the rest. You'll need to enter the username and password you put in motor_blog.conf. In the "General" tab of your blog's settings, I suggest setting "Download the 1000 most recent posts on refresh," since Motor-Blog can handle it. Under "Editing," set Preview Text Filter to "Markdown", and Image Size "Defaults To Full Size".
When you're editing a post, do "View -> Excerpt" to edit the post's meta-description. This text appears in Google results as a snippet, or when sharing a link to the post on Facebook. Motor-Blog refuses the post if the meta-description field is over 155 characters. Do "View -> Slug Field" to set a custom slug as the final part of the post's URL. If you leave the slug empty, Motor-Blog slugifies the title.
Finally, you'll want to customize how MarsEdit inserts images.
This customization serves two purposes: first, we'll remove the width and height
img tags so Motor-Blog's responsive layout can fit them to the visitor's screen.
Second, we'll set images' title text is set to the same value as their alt-text,
since browsers display image titles as tooltips.
Open the MarsEdit Media Manager and select an image.
In the Media Manager's lower-right corner is a "Style" chooser,
with the option "Customize...":
Choose this and create a new image style with "opening markup" like this:
<img style="display:block; margin-left:auto; margin-right:auto;" src="#fileurl#" alt="#alttext#" title="#alttext#" />
```python print "foo" ```
The list of languages
is whatever Pygments supports. The following are of
interest to Python coders like me:
py3tb for tracebacks, and
Using a feature in the latest Python-Markdown, you can highlight specific lines in a code block:
```python hl_lines="2" # Line 1. # Line 2. This will have a yellow background ```
- Set your theme directory in
- The theme directory should contain a
templatessubdir with the same set of filenames as the example theme. Tornado templates or Jade templates are both supported.
- Follow the example theme for inspiration.
setting()function is available to all templates, and gives access to values in
A Tour of the Code
- server.py: Web application server
- motor_blog/: Package code
- handlers.py: RequestHandlers for the blog's website
- admin-templates/: Templates for login/out and viewing drafts
- theme/: Default theme for emptysquare.net, overridable with your theme
- api/: The XML-RPC API that MarsEdit uses
- models.py: schema definitions
- markup.py: convert from Markdown into HTML for display, including some custom syntax
- wordpress_to_markdown.py: convert from the WordPress's particular HTML to markdown, for migrate_from_wordpress.py
- abbrev.py: convert from HTML to truncated plain text for all-posts page
- migrate_from_wordpress.py: Tool for migrating from my old Wordpress blog to Motor-Blog. I wrote this tool when Motor didn't support GridFS, so it puts all media from Wordpress into single documents in the "media" collection, which brings us to...
- migrate_media_to_gridfs.py: Tool to migrate media from a single document per image in the "media" collection to GridFS.
- cache.py: Cache results from MongoDB, invalidate when events are emitted
- indexes.py: Index definitions for
- options.py: Configuration parsing