Archive for the 'blogggg!' Category
blogggg! A blog engine for the ages.
In the past 3 years, blogs have popped up faster than Starbucks locations, and we want to be the first to say: “Me too!” Ok, maybe we’re not the first to be the second, but that’s not going to stop us from cramming the world’s already-full blog hole with yet another blog engine. We’re jumping onto the dog pile… er… “blog pile.”
You might ask, “why?” Because it’s easy; that’s why!! It’s so easy that it seems people just can’t help themselves. We’re no different. Here’s a history lesson:
In the beginning, there was static content. And it was good. But then there was a problem: it was fast and didn’t use enough bandwidth. What good are fat pipes if you’re not going to cram them full of bloat?

Enter: “The blog”
What is it you ask? It’s static content, but served dynamically!!! This is the kind of thing we can get behind. Plus, it has the added bonus of being able to trivially produce eye-rot candy like tag clouds.
Blogggg!
To the point, we’ve written our own blog software: Blogggg! If you’re going to compete with all 100+ other blog engines out there, you need to have a catchy name. Our is super catchy because you say it like “blog” but you say it like you’re on meth. The exclamation point is absolutely mandatory as its emphatic qualities underscore our gratuitous use of the letter: “g”. It’s a recipe for success!!!
Design
We’re living in a database-driven world… no use in trying to change that now. Since SQL can be really hard (and you know how we hate solving hard problems), how will we overcome our debilitating laziness while simultaneously being a sheep in web 2.0 flock? Luckily, we aren’t the first programmers to try and avoid this mysterious and ancient SQL technology. We turn to Object Relational Mapping.
We here at Code Irony worship “The Python” no matter what it ends up costing us in our careers or hygiene. We need an ORM and we have The Snake… That can mean only one thing: sqlalchemy (not true… ORMs grow on trees). Sit back and watch the hits come in. Brilliant!!!!
The Code
There are two parts to blogggg! — submitting a blog post, and viewing it. When you submit the post, it is stored in a database backend using the code below. The first time you run the post code, you’ll need to feed it the command “create_db” — this will set up the magical database backend for you (don’t worry about understanding that part).
>python post.py create_db
Once this is set up, write your text to a file, and run the post command again, only with your post file as the input:
>python post.py mypost.html
Then, when you want to view your static content, you use the view code, as shown below. To get a simple server going, just run:
>python serve.py
And then navigate in your browser to http://localhost:8080/mypost.html. Look, there’s your post!
It’s so simple! And no SQL was necessary! We’re well on our way to serving this static content as fast as the Python interpreter can!

Deployment
Blogggg! will only work locally using the code above. Our blog software needs to be deployed for the real world — how else will thousands of people be able to view our witty static content?!?!?
First, we need to set up our code to run in a served environment. We’ll use Apache to get rid of that silly :8080 after the domain. Then, we’ll need to install mod_fastcgi on Apache. If you don’t know how to do that, use Google — it’ll practically compile itself! Just like that scene in Fantasia.
Then install flup… it’ll do convert the output from our application into something that Apache can use. You can use:
>easy_install flup
Then, at the top of the serve.py file, add this:
#!/usr/bin/python from flup.server.fcgi import WSGIServer
and at the bottom, add this:
app = cherrypy.tree.mount(MyBlog())
cherrypy.engine.start(blocking=False)
try:
WSGIServer(app).run()
finally:
cherrypy.engine.stop()
Then in httpd.conf, add these lines:
FastCgiIpcDir /tmp
FastCgiServer /path/to/serve.py -idle-timeout 120 -processes 4
and in your directory that you’re serving from, add a file named .htaccess with this inside:
AddHandler fastcgi-script .py
ScriptAliasMatch (.*$) /path/to/cherry.py$1
If you’ve been following, you can now go to your domain name, append “myentry.html” and you’ll see your text! It was so simple! If there’s an easier way to serve static content, be sure to let us know (but we’ll be skeptical for sure!)!
post.py
# Filename: post.py # Revision: 0.1 # # Copyright 2008 Christopher Myers and Justin Davis # # blogggg! poster # Load the content, and you’re almost done # # You have unlimited license to use this software however you want. There # is no warranty either expressed nor implied. Actually, we recommend not # using it. It just exists to prove a point. from sqlalchemy import * import datetime db = create_engine(’sqlite:////home/guido/blogg.db’) meta = MetaData(db) blog_entries = Table(‘entries’, meta, Column(‘entry’, String(), primary_key = True), Column(‘url’, String()), Column(‘date’, DateTime, default=datetime.datetime.now()) ) class Entry(object): def __init__(self, text, url): self.entry = text self.url = url orm.mapper(Entry, blog_entries) session = orm.create_session(bind=db) if __name__ == “__main__”: import sys if sys.argv[1] == “create_db”: blog_entries.create(bind=db) else: f = open(sys.argv[1]).read() entry = Entry(f, sys.argv[1]) session.save(entry) session.flush()
serve.py
# Filename: serve.py # Revision: 0.1 # # Copyright 2008 Christopher Myers and Justin Davis # # blogggg! server # Now, watch the hits come in! # # You have unlimited license to use this software however you want. There # is no warranty either expressed nor implied. Actually, we recommend not # using it. It just exists to prove a point. import postimport cherrypy class MyBlog: def default(self, url): my_query = post.session.query(post.Entry) my_entry = my_query.filter_by(url=url).first() return my_entry.entry default.exposed = True cherrypy.quickstart(MyBlog())20 comments