Getting Started with Flask

This tutorial describes how to create a simple Flask application and set it up under Apache on OS X. Flask is a microframework written in Python. The source code is based on the Flask tutorial. The source code for this tutorial can be found on Github.

As in the tutorial on Flask website, we will create the simple Flaskr blog.

First, create a folder for the project at some convenient location: e.g. ~/flaskr.

In the project root, create two folders static and templates.

In the root folder, create a file flaskr.py containing the following code:

import sqlite3
from flask import Flask, request, session, g, redirect, url_for, \
    abort, render_template, flash
from contextlib import closing

# configuration
DATABASE = '/tmp/flaskr.db'
DEBUG = True
SECRET_KEY = 'developmentn key'
USERNAME = 'admin'
PASSWORD = 'default'

app = Flask(__name__)
app.config.from_object(__name__)

def connect_db():
    return sqlite3.connect(app.config['DATABASE'])

@app.before_request
def before_request():
    g.db = connect_db()


@app.teardown_request
def teardown_request(exception):
    db = getattr(g, 'db', None)
    if db is not None:
        db.close()

def init_db():
    with closing(connect_db()) as db:
        with app.open_resource('schema.sql', mode='r') as f:
            db.cursor().executescript(f.read())
        db.commit()

@app.route('/')
def show_entries():
    cur = g.db.execute('select title, text from entries order by id desc')
    entries = [dict(title=row[0], text=row[1]) for row in cur.fetchall()]
    return render_template('show_entries.html', entries=entries)


@app.route('/add', methods=['POST'])
def add_entry():
    if not session.get('logged_in'):
        abort(401)
    g.db.execute('insert into entries (title, text) values(?,?)',
                 [request.form['title'], request.form['text']])
    g.db.commit()
    flash('New entry was successfully posted')
    return redirect(url_for('show_entries'))

@app.route('/login', methods=['GET', 'POST'])
def login():
    error = None
    if request.method == 'POST':
        if request.form['username'] != app.config['USERNAME']:
            error = 'Invalid username'
        elif request.form['password'] != app.config['PASSWORD']:
            error = 'Invalid password'
        else:
            session['logged_in'] = True
            flash('You were logged in')
            return redirect(url_for('show_entries'))
    return render_template('login.html', error=error)

@app.route('/logout')
def logout():
    session.pop('logged_in', None)
    flash('You were logged out')
    return redirect(url_for('show_entries'))

if __name__ == '__main__':

    app.run()

Now some explanation. In connect_db() we return a connection to the database, which is sqlite3 in this case.

before_request() function is a function that gets called before every request. We use it to create a db attribute on g which we can use for db requests.

teardown_request() function gets called at the end of a request. This allows us to close the request.

init_db() allows us initialise the database.

The function show_entries() is used to show blog entries, fetching data first from the database.

add_entry() is used to add new blog posts via POST method. The post gets added to the db as well.

login() is used to log the user in. We hardcode the username and password to that which is in our configuration. We also store a flag logged_in in the session on logging in.

logout() is used to log the user out.

Then create a db schema file schema.sql with the following contents:

drop table if exists entries;
create table entries (
id INTEGER PRIMARY KEY autoincrement,
title text not null,
text text not null
);

Next, create a file layout.html in templates folder with the following content:

<!doctype html>
<title>Flaskr</title>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}" >
<div class=page>
<h1>Flaskr</h1>
    <div class=metanav>
        {% if not session.logged_in %}
        <a href="{{ url_for('login') }}">log in</a>
        {% else %}
        <a href="{{ url_for('logout') }}">log out</a>
        {% endif %}
    </div>
    {% for message in get_flashed_messages() %}
    <div class=flash>{{ message }}</div>
    {% endfor %}
    {% block body %}{% endblock %}
    </div>

This file contains the overall layout of the app and a body block which will include the body of specific pages.

Next, create login.html in the same folder containing the following:

{% extends "layout.html" %}
{% block body %}
  <h2>Login</h2>
  {% if error %}<p class=error><strong>Error:</strong> {{ error }}{% endif %}
  <form action="{{ url_for('login') }}" method=post>
    <dl>
      <dt>Username:
      <dd><input type=text name=username>
      <dt>Password:
      <dd><input type=password name=password>
      <dd><input type=submit value=Login>
    </dl>
  </form>
{% endblock %}

This form contains markup for the form. As you can see it extends layout.html.

Also, create a file show_entries.html in the same folder with the following content:

{% extends "layout.html" %}
{% block body %}
    {% if session.logged_in %}
    <form action="{{ url_for('add_entry') }}" method=post class=add-entry>
        <dl>
            <dt>Title:</dt>
            <dd><input type="text" size="30" name="title">
            <dt>Text:
            <dd><textarea name=text rows="5" cols="40"></textarea></dd>
            <dd><input type="submit" value="Share"/></dd>

        </dl>
    </form>
    {% endif %}
    <ul class="entries">
        {% for  entry in entries %}
        <li><h2>{{ entry.title }}</h2>{{ entry.text|safe}}</li>
        {% else %}
        <li><em>Unbelievable. No entries here so far</em></li>
        {% endfor %}
    </ul>
{% endblock %}

Here we show post add form and a list of posts if any.

There, now we have the files. To set up the project, create a virtualenv, e.g. flasktest. As follows:

mkvirtualenv flasktest

Then change to the project root folder and install Flask as follows:

pip install Flask

Then run the project using command:

python flaskr.py

Some lines should appear in the terminal indicating the project has started.

You can now view the blog by visiting http://localhost:5000 in your browser.

To set up the project on production, you can use several means including running it via WSGI behind Apache.

First, install flup, a package that provides an random assortment of WSGI servers, using the command:

pip install flup

Next, create a file flaskr.wcgi with the following content:

#!/usr/bin/python
from flup.server.fcgi import WSGIServer
from flaskr import app as application

if __name__ == '__main__':
    WSGIServer(app).run()

Next, install WSGI. If using OS X, you can do that using the command:

brew install homebrew/apache/mod_wsgi

After installation, you’ll see a line telling you to add a line to your apache config file in order to finish installation.

Then add the line to your httpd.conf file. It should be something like:

LoadModule wsgi_module /usr/local/Cellar/mod_wsgi/4.4.11/libexec/mod_wsgi.so

Then, create an Apache configuration file containing the following content:

<VirtualHost *:80>
ServerName flaskr.localhost
WSGIScriptAlias / /path/to/flaskr/flaskr.wsgi
<Directory "/path/to/flaskr/">
Options +Indexes +FollowSymLinks
AllowOverride all
Require all granted
</Directory>
WSGIDaemonProcess flaskr python-path=/path/to/flaskr:/path/to/flaskrvirtualenv/lib/python2.7/site-packages
WSGIProcessGroup flaskr
</VirtualHost>

Next, restart apache as follows:

sudo apachectl restart

Create an entry in your hosts file if necessary to make flaskr.localhost load for you.

That’s it! You should now be able to access your app at http://flaskr.localhost/

Enjoy!

Creating a Simple app with CherryPy and React JS

Hi folks,

In this tutorial we will set up a simple web app using CherryPy and React js. This tutorial is based on the first tutorial on the CherryPy website with some minor updates necessary to make it work.

First, create a virtual environment, say cherrypyapp using the command:

mkvirtualenv cherrypyapp

The above command switches you to the environment on creation.
Next, install CherryPy using the following commands:

hg clone https://bitbucket.org/cherrypy/cherrypy
cd cherrypy
python setup.py install

Note: As of the time of writing the pip version didn’t seem to work well. On testing the installation there was an error about tutorial.conf not being found, hence my using hg.

Test your installation using command:

python -m cherrypy.tutorial.tut01_helloworld

You should see several lines of text show up with the last line containing the text:

ENGINE Bus STARTED

Now we’re ready to create a project. Create a folder for the project, say ~/Documents/cherrypyapp and change to the directory.

Just like in the tutorial on CherryPy website, we’re going to create a sample app that generates a random string of a user-supplied length (8 by default). The app will allow you edit or delete the string. SQLite db will be used to store the string generated.

Create a file cherrypyapp.py containing the following content:

import os, os.path
import random
import sqlite3
import string
import time

import cherrypy

DB_STRING = "my.db"

class StringGenerator(object):
   @cherrypy.expose
   def index(self):
       return file('index.html')


class StringGeneratorWebService(object):
    exposed = True

    @cherrypy.tools.accept(media='text/plain')
    def GET(self):
        with sqlite3.connect(DB_STRING) as c:
            cherrypy.session['ts'] = time.time()
            r = c.execute("SELECT value FROM user_string WHERE session_id=?",
                      [cherrypy.session.id])
            return r.fetchone()

    def POST(self, length=8):
        some_string = ''.join(random.sample(string.hexdigits, int(length)))
        with sqlite3.connect(DB_STRING) as c:
            cherrypy.session['ts'] = time.time()
            c.execute("INSERT INTO user_string VALUES (?, ?)",
                      [cherrypy.session.id, some_string])
        return some_string

    def PUT(self, another_string):
        with sqlite3.connect(DB_STRING) as c:
            cherrypy.session['ts'] = time.time()
            c.execute("UPDATE user_string SET value=? WHERE session_id=?",
                      [another_string, cherrypy.session.id])

    def DELETE(self):
        cherrypy.session.pop('ts', None)
        with sqlite3.connect(DB_STRING) as c:
            c.execute("DELETE FROM user_string WHERE session_id=?",
                      [cherrypy.session.id])

def setup_database():
    """
    Create the `user_string` table in the database
    on server startup
    """
    with sqlite3.connect(DB_STRING) as con:
        con.execute("CREATE TABLE user_string (session_id, value)")

def cleanup_database():
    """
    Destroy the `user_string` table from the database
    on server shutdown.
    """
    with sqlite3.connect(DB_STRING) as con:
        con.execute("DROP TABLE user_string")

if __name__ == '__main__':
    conf = {
        '/': {
            'tools.sessions.on': True,
            'tools.staticdir.root': os.path.abspath(os.getcwd())
        },
        '/generator': {
            'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
            'tools.response_headers.on': True,
            'tools.response_headers.headers': [('Content-Type', 'text/plain')],
        },
        '/static': {
            'tools.staticdir.on': True,
            'tools.staticdir.dir': './public'
        }
    }

    cherrypy.engine.subscribe('start', setup_database)
    cherrypy.engine.subscribe('stop', cleanup_database)

    webapp = StringGenerator()
    webapp.generator = StringGeneratorWebService()
    cherrypy.quickstart(webapp, '/', conf)

The StringGenerator class contains an index() function which handles the home page link. As seen, it just outputs the contents of index.html.

StringGeneratorWebService is a class that provides a RESTful API for creating, updating and deleting a string which we generate in the front end. The setup_database() function creates the user_string table and the cleanup_database() function drops it.

In the conf variable the line ‘request.dispatch’: cherrypy.dispatch.MethodDispatcher() indicates that we will use HTTP request methods that match the name of functions within the StringGeneratorWebService class.

Next, create a file index.html with the following contetent:

<!DOCTYPE html>
<html>
 <head>
 <link href="/static/css/style.css" rel="stylesheet">

 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react-dom.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

 </head>
 <body>
 <div id="generator"></div>
 <script type="text/babel" src="static/js/gen.js"></script>
 </body>
</html>

Note the script type “text/babel”. That’s important. Don’t use just javascript, or else it may not work.

Next, create a folder public/css. Then create a file style.css inside it with the following content:

body {
  background-color: blue;
}

#the-string {
  display: none;
}

Then create a folder public/js and a file gen.js inside it with the following content:

 var StringGeneratorBox = React.createClass({
   handleGenerate: function() {
     var length = this.state.length;
     this.setState(function() {
       $.ajax({
         url: this.props.url,
         dataType: 'text',
         type: 'POST',
         data: {
           "length": length
         },
         success: function(data) {
           this.setState({
             length: length,
             string: data,
             mode: "edit"
           });
         }.bind(this),
         error: function(xhr, status, err) {
           console.error(this.props.url,
             status, err.toString()
           );
         }.bind(this)
       });
     });
   },
   handleEdit: function() {
     var new_string = this.state.string;
     this.setState(function() {
       $.ajax({
         url: this.props.url,
         type: 'PUT',
         data: {
           "another_string": new_string
         },
         success: function() {
           this.setState({
             length: new_string.length,
             string: new_string,
             mode: "edit"
           });
         }.bind(this),
         error: function(xhr, status, err) {
           console.error(this.props.url,
             status, err.toString()
           );
         }.bind(this)
       });
     });
   },
   handleDelete: function() {
     this.setState(function() {
       $.ajax({
         url: this.props.url,
         type: 'DELETE',
         success: function() {
           this.setState({
             length: "8",
             string: "",
             mode: "create"
           });
         }.bind(this),
         error: function(xhr, status, err) {
           console.error(this.props.url,
             status, err.toString()
           );
         }.bind(this)
       });
     });
   },
   handleLengthChange: function(length) {
     this.setState({
       length: length,
       string: "",
       mode: "create"
     });
   },
   handleStringChange: function(new_string) {
     this.setState({
       length: new_string.length,
       string: new_string,
       mode: "edit"
     });
   },
   getInitialState: function() {
     return {
       length: "8",
       string: "",
       mode: "create"
     };
   },
  render: function() {
     return (
       <div className="stringGenBox">
     <StringGeneratorForm onCreateString={this.handleGenerate}
     onReplaceString={this.handleEdit}
     onDeleteString={this.handleDelete}
     onLengthChange={this.handleLengthChange}
     onStringChange={this.handleStringChange}
     mode={this.state.mode}
     length={this.state.length}
     string={this.state.string}/>        
       </div>
     );
   }
 });

 var StringGeneratorForm = React.createClass({
   handleCreate: function(e) {
     e.preventDefault();
     this.props.onCreateString();
   },
   handleReplace: function(e) {
     e.preventDefault();
     this.props.onReplaceString();
   },
   handleDelete: function(e) {
     e.preventDefault();
     this.props.onDeleteString();
   },
   handleLengthChange: function(e) {
     e.preventDefault();
     var length = React.findDOMNode(this.refs.length).value.trim();
     this.props.onLengthChange(length);
   },
   handleStringChange: function(e) {
     e.preventDefault();
     var string = React.findDOMNode(this.refs.string).value.trim();
     this.props.onStringChange(string);
   },
   render: function() {
     if (this.props.mode == "create") {
       return (
         <div>
            <input type="text" value="{this.props.length}" />
            <button>Give it now!</button>
         </div>
       );
     } else if (this.props.mode == "edit") {
       return (
         <div>
            <input type="text" value="{this.props.string}" />
            <button>Replace</button>
            <button>Delete it</button>
         </div>
       );
     }

     return null;
   }
 });

 React.render(
   <StringGeneratorBox url="/generator" />,
   document.getElementById('generator')
 );

Note form the javascript file that the StringGeneratorBox displays the main container and inside it is the StringGeneratorForm which handles showing the form.

Now we have all the files in place, start the server using the command:

python cherrypyapp.py

You should then be able to visit the site in a browser at http://localhost:8080/

That’s all for now. Enjoy.

Sources

Tutorial | React. https://facebook.github.io/react/docs/tutorial.html

Tutorials — CherryPy 3.8.2 documentation. http://docs.cherrypy.org/en/latest/tutorials.html

How to use PostgreSQL with Django on OS X

In this tutorial I’ll describe how to use PostgreSQL with Django running on OS X.

First, install PostgreSQL. You can do this using several methods. For this tutorial we use brew by running the following command in a terminal:

    brew install postgresql

Next, start the PostgreSQL server by running the following command:

    postgres -D /usr/local/var/postgres

Note: For information on how to make PostgreSQL start automatically run the command:

    brew info postgres

Now we’ve started postgress, we can create a database called myproject by running the following command:

    createdb myproject

Next, log into the Postgres session in the terminal by running

    psql myproject

Then create a user for the project using the command:

    CREATE USER myprojectuser WITH PASSWORD 'password';

Next, set encoding, transaction isoloation (to block reads from uncommitted transactions) and timezone using the following commands:

    ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
    ALTER ROLE myprojectuser SET default_transaction_isolation \
 TO 'read committed';
    ALTER ROLE myprojectuser SET timezone TO 'UTC';

Next, grant the db user privileges with the command:

    GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;

Exit the SQL session using the command:

    Ctrl D

Now we are going to install Django. I assume you have virtualenvwrapper installed.

Create your new virtual environment using the command:

    mkvirtualenv myprojectenv

This creates and switches to the new environment.

In here we then install Django and Psycopg2 using the commands:

    pip install django psycopg2

Next, create a folder at a suitable location for your project using the commands:

    mkdir ~/myproject
    cd $_

Then create a Django project in the created folder using the command:

    django-admin.py startproject myproject .

Next, we need to tell Django to use Postgres since it uses SQlite by default. Open myproject/settings.py with your favourite editor.

Find the lines:

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }

And change it to

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'myproject',
            'USER': 'myprojectuser',
            'PASSWORD': 'password',
            'HOST': 'localhost',
            'PORT': '',
        }
    }

Now we shall migrate the database using the following commands:

    python manage.py makemigrations
    python manage.py migrate

Note: On running the first command you may see an output saying No changes were detected. Ignore it.

You may now create a superuser using the command:

python manage.py createsuperuser

Now that is done, you may start your server using the command:

    python manage.py runserver 0.0.0.0:8000

That’s it! You can now view your site by visiting http://localhost:8000 in your browser. You should see the default index page. Using the admin credentials you created earler, you should be able to log in to the admin at http://localhost:8000/admin

Sources

How To Use PostgreSQL with your Django Application on Ubuntu 14.04 | DigitalOcean. https://www.digitalocean.com/community/tutorials/how-to-use-postgresql-with-your-django-application-on-ubuntu-14-04

PostgreSQL: Documentation: 9.4: PostgreSQL 9.4.5 Documentation. http://www.postgresql.org/docs/9.4/static/index.html

How to view all programs listening on a specific port

In this post I discuss how to check what program is listening to a port on Ubuntu.

The command to use is

netstat -anp <port number> 

The “a” option means that all sockets should be shown, both listening and non-listening ones. The “n” option means numeric. By default netstat translates ports to their service name, making it more difficult to search ports by number. This option solves that. Finally, the “p” option shows the PID and name of the program so that you can tell exactly what’s listening to a port.