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 so far
Leave a reply
“Powered by WordPress” ????
Thats not enough bloat to be called a real blog!
You should try Ruby on Rails sometime, no THERE is bloat
@Marcus
Shhhh! Don’t tell anyone!
You suck! You are using SQLite, it does not scale and is too easy to setup … you need a REAL database to properly serve your content. A Postgresql cluster is mandatory for this kind of high level application!
Also I would recommend to design your own wiki syntax to write your blog post:
dickhead is too complicated. *[[dickhead]]* is much more easy to understand (” *[[]]*? of course it will emphasise the text! or underline it ? or a turn it into a link maybe ?”)
This site partially restores my faith in humanity.
Remember folks that it cannot be a professional blogging tool unless it sends lots of Javascript to the client.
Two things:
1) Why only 4 “g’s” in “blogggg!” ? Or, will it be dymamic based on how many posts are in the blog (much like the number o’s in google increase based on the pages of results)?
So, if there are 10 posts, it would be: “blogggggggggg!”.
This way visitors will know how many posts there are and if there is a new post (from counting the number of g’s and doing a diff based on their last count).
I’m sure you could figure out a super bloated way of coding that functionality. For instance, each “g” could be a 1MB, 500×500px bmp that you shrink down to 5×5px via the tag in the html code.
2) I also think you should look into hosting this site with your software at blogggg.com.
The number of g’s in the domain name should also be dynamic based on the number of posts.
So, initially there would be 1 post and we would go to: http://blogggg.com.
If there are 20 posts, we type in 4 + 19 g’s: http://bloggggggggggggggggggggggg.com
Hey, that also enables us to easily jump to specific posts. Want to go to the 3rd post? Then go to: http://blogggggg.com (4 + 2 g’s).
Simple!
Fuck Henry’s comment. This looks good. Are you running this engine for this blog right now? If so, add some pretty URL capabilities.
> Column(‘date’, DateTime, default=datetime.datetime.now())
I suppose it’s preferable to restart the server once a day to get correct post dates
Сегодня я много читал по этому вопросу….
Администратор, менеджер […….
Вы не эксперт?…
Аниматор […….
PillSpot.org. Canadian Health&Care.Special Internet Prices.No prescription online pharmacy.Pillspot.org.< b > < a href=”http://pillspot.org/products/vitamins_herbal_supplements/ Herbal-supplements@buy.online” >.< /a >…
Categories: Vitamins/Herbal Supplements.Antidepressants.Stomach.Womens Health.Mens Health.Antiviral.Stop SmokingMental HealthAntibiotics.Pain Relief.Antidiabetic.Anti-allergic/Asthma.Blood Pressure/Heart.Skin Care.Eye Care.Anxiety/Sleep Aid.Weight…
< blockquote >< a href=”http://pillspot.org/”>PillSpot.org. Canadian Health&Care.Best quality drugs.No prescription online pharmacy.Special Internet Prices. No prescription drugs. Buy pills online< /a >…
Buy:Levitra.Viagra Super Force.Cialis Super Active+.Zithromax.Super Active ED Pack.Tramadol.Viagra Super Active+.Propecia.Cialis.Maxaman.Viagra.Viagra Professional.Soma.VPXL.Cialis Professional.Cialis Soft Tabs.Viagra Soft Tabs….
< blockquote >< a href=”http://medicamentspot.com/”>MedicamentSpot.com. Canadian Health&Care.No prescription online pharmacy.Special Internet Prices.Best quality drugs. High quality drugs. Order drugs online< /a >…
Buy:Seroquel.Nymphomax.Lipitor.Advair.Acomplia.SleepWell.Zetia.Aricept.Benicar.Female Cialis.Wellbutrin SR.Zocor.Buspar.Lasix.Ventolin.Cozaar.Lipothin.Amoxicillin.Female Pink Viagra.Prozac….
trader http://AUTOTECHGUIDE.INFO/tag/trader joe\x27s : joe\x27s…
trader…
HD28 http://gmartini6cp.AUTOPARTSTHAI.INFO/tag/HD-28+d+HD28/ : HD28…
HD-28…
kitchen http://gkitchenaidybpf.AACEHARDWARE.INFO/tag/kitchen+aid+range+Gas/ : Gas…
Gas…
r2 http://aantigquesbu6pv.03GMCPARTS.US/tag/r2+100+8870/ : 100…
r2…
commercial http://fbathroomvvzhgo.04FORDPARTS.US/tag/commercial+bathroom+Air/ : bathroom…
commercial…
Design http://yyellowdtpzv.BESTPARTSPLUS.INFO/tag/Free+Design+Your/ : Design…
Design…