_
                                 | |
     ____  _____ ____   ___  ____| |__  _____ ____    ____ ___  ____
    |  _ \(____ |    \ / _ \/ ___)  _ \(____ |  _ \  / ___) _ \|    \
    | | | / ___ | | | | |_|( (___| | | / ___ | | | |( (__| |_| | | | |
    |_| |_\_____|_|_|_|\___/\____)_| |_\_____|_| |_(O)____)___/|_|_|_|

,.-~*´¨¯¨`*·~-.¸-(monoSpaceBlog)-,.-~*´¨¯¨`*·~-.¸

2012-01-24 22:37:01.348463 UTC

Cooking Python Soup With Namochan. That sounds stupid. I'll figure another name as we go. I don't pretend to be a professional coder, most of my code is probably far from "pythonic". But who else would be better to write a tutorial how to install the tools and make a blog from scratch than another newbie? 

Ingredients:

Virtual Server
First, we need a server. vserver.de was a cheap and has so far been pretty reliable service.

Nginx
I hate apache. Ok, maybe not HATE, but I don't like to use it on my servers. It seems way too heavy for my purposes. Nginx is simple to configure and lightweight.

Python
I hate PHP, I really do. Python might not be the hipster way to go, but I get things done with it! That's way more important than anything else. Without getting done, there is nothing.

Flask
I don't dream of coding everything myself, that isn't even what python is all about. Django is pretty nice, but I like to start from an empty slate and not with ready made directories of configurations I don't fully understand. Flask is small, simple, fast... amazing?

SQLAlchemy
Again, I hate (starting to sound like a negative person here) dealing with SQL request by hand. SQLAlchemy deals with that for me and let's me use django like models. I make an object, I get a table. I give it a variable, I get a column. 

TinyMCE
Who'd type HTML tags by hand when you can use a WYSIWYG javascript magic editor. At least I hope M stands for magic. Tiny Magic Collectors Edition, yeah that's it.

FastCGI
Something needs to bind Flask into Nginx. This is done streaming the stuff into a unix sock. Apparently socks have a second different purpose I don't fully understand. User <-> Nginx <-> sock <-> Flask <-> Python code. I guess that sounds about right.



,.-~*´¨¯¨`*·~-.¸-(Day 1)-,.-~*´¨¯¨`*·~-.¸

2012-01-24 23:45:11.697962 UTC

So, first we need to set up the environment for the blog. We don't want to use the python installation on the server. This would lead to problematic situations when you update a library for one site and it break another. To make a new installation just for the blog, we use virtualenv.

So, first we'll make the directories.

mkdir /var/www/monospace

mkdir: cannot create directory `/var/www/monospace': Permission denied

Don't you just hate when that happens?

sudo !! 

Always makes me happy when I get to yell at bash. Ok, that's more like it. Let's install virtualenv.

apt-get install python-virtualenv

virtualenv --no-site-packages /var/www/monospace/env

There, now we should have a clean installation of python in the directory of our future blog. The --no-site-packages means that we don't want any previously installed python packages with our new python. This is a default behavior on newer virtualenv, but just to be sure that we don't copy all pygames and whatnot, I like to use that. To activate the environment, we type:

source /var/www/monospace/env/bin/activate

Now there should be a little (env) in front of the prompt, that means the python we now use is the one in the monospace directory. Now we need some libraries in there.

pip install flask

pip install flask-sqlalchemy

pip install flup

I can't believe that last one is a real command. Anyways, if everything went ok, we now have everything we need to start coding away! Open your favorite editor and make a new file:

/var/www/monospace/monospace.py

And type something like this:

problem?
Yes, it's an image. I fully recommend you type these yourself. Don't worry, I don't plan being a dick all the way through. Where was I...

@app.route("/") tells flask that if someone requests the root url, it'll call the function "hello". Anything that is returned from the function will be sent to the client. 

So now you can run the program. It'll make a new host, at 127.0.0.1:8080. You can access it only locally, so if you're at a remote server, you need to add your IP address inside app.run() like so:

app.run(host="192.168.0.1",port=8080)

Now you can access it from a remote server. All you should see this:

Hello World!

It's not a proper server yet, and it doesn't even send HTML, it's just text. Next up is jinja templates. 



,.-~*´¨¯¨`*·~-.¸-(Day 2)-,.-~*´¨¯¨`*·~-.¸

2012-01-25 00:39:36.886865 UTC

Jinja, sounds like ninja so it must be awesome. It is. 

Make a new directory called "templates" inside the monospace directory.

mkdir /var/www/monospace/templates

And while we're at it, let's make another one:

mkdir /var/www/monospace/static

These are directories that Flask uses to get jinja templates, and static files like css styles and images. Let's make a simple jinja template.

file: /var/www/monospace/template/index.html

<!DOCTYPE html>
<html>
 <head>
  <title>monospace blog</title>
 </head>
 <body>
  {{ content }}
 </body>
</html> 

And the we'll edit the monospace.py file to use templates. First, add "render_template" in the imports.

from flask import Flask, render_template

Then replace the return value to:

return render_template("index.html",content="Hello world!")

If the server is running, it will probably see the change and reload the files. Look at the page again. It should have a title now, and proper html. The {{ content }} is a jinja tag, and will insert the contents of content at the content tag... Yo dawg, I herd you like content.

All this allows us to make a template of what the page should look like, and just replace these tags with stuff we come up with in python. And that's not all. We can make more functionality using "if" and "for" tags. Like this:

{% for post in content %}
<h1>{{ post.title }}</h1>
<p>{{ post.body }}</p>
{% endfor %}

If you now change the content="Hello world!" inside monospace.py into:

content=[{"title":"Hello world!","body":"First post, kinda."}]

it will repeat the one part of html for every entry in the list, taking each dict in post variable. Dict keys can now be accessed with {{ post.title }} and {{ post.body }}.  Each title will be inside <h1> tags and each body inside <p> tags.

Here's a snapshot of progress so far:
monospace_day2.zip



,.-~*´¨¯¨`*·~-.¸-(Day 3)-,.-~*´¨¯¨`*·~-.¸

2012-01-25 11:09:00.786549 UTC

Today is about SQLAlchemy. It makes life with SQL a bit easier. First, we'll need to import it to the app.

from flaskext.sqlalchemy import SQLAlchemy

I also like to use sqlite, it keeps the database in a local file and doesn't need any user authentication to use (beside the obvious file ownership).

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///./sqlite.db'

This should make a new sqlite database right in the directory we are right now. While we are at it, let's put more configurations for Flask too.

from werkzeug.security import generate_password_hash, check_password_hash

SECRET_KEY = 'dev key 1234'
app.config.from_object(__name__)
db = SQLAlchemy(app)

This will tell Flask to salt sessions with that key. Otherwise, the user would be able to change their cookies to say they are logged in as admin and other nasty stuff. So keep it safe, keep it hidden. Also, don't use the exact same string for SECRET_KEY and wear sunscreen.

db is the database, we will communicate with sqlite through this, without ever typing any SQL manually.

To tell SQLAlchemy what we want to store in the database, we need to make a class. Let's make a "Post" class first.

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    content = db.Column(db.String)
    body = db.Column(db.String)
    def __init__(self,title,content):
        self.title = title
        self.content = content
    def __repr__(self):
        return "<Post %r>" % self.id

To break it down, let's start from the top. Post inherits db.Model, which is a model of SQLAlchemy, a way for it to understand our object. Inside the Post, we have the columns for out Table.

id, which is an integer and the primary_key, this means the it will always be different and a number starting from 1. It will be the main indentifier for posts.

title and body are pretty self explanatory, they are strings that contain our posts title and the main content.

What I like to do, is to make a self-destruct button on my website. You should disable this when you deploy your site, especially if you write a tutorial how to wipe clean your sites database from an url.

It goes something like this:

@app.route("/reset/")
def reset():
    db.drop_all()
    db.create_all()
    db.session.add(Post("First post","from sqlite too!"))
    db.session.commit()
    return "System has been reset"

Now, when we open the url localhost:8080/reset/, the reset function will first delete the whole database with db.drop_all(), then it will create the empty tables according to the models we provided with db.create_all(). To test it out, we add a new Post in the session with db.session.add(), inside it we provide Post's init function with the title and the content.

db.session.commit() will save the changes. We are now done, there is one post in our database.

To make our site show this, we'll need to adjust the index function a bit. 

@app.route("/")
def index():
    return render_template("index.html",content=Post.query.all())

Now instead of giving a dict to the jinja inside content, we make a query of the Posts and give the results. Go ahead and try the page now. It should now show the results of our sqlite database.

Next, I think we need a "new post" page.

Status right now,
monospace_day3.zip