Tuesday, 17 July 2012

A First Look at Flask-Evolution

While poking around in Flask-Ahoy this morning I came across Flask-Evolution which I hadn't previous noticed. It offers the Django idea of migrations to the Flask community and so I thought I'd give it a go and see how it shapes up.


So let's set up a virtual environment and get the basics in place.
mkvirtualenv evo;
cdvirtualenv
# this installs flask, flask-script and everything you need
pip install Flask-Evolution
touch myapp.py
touch manage.py
view raw evo.sh hosted with ❤ by GitHub

Now the contents of the two files you touched. First the "hello world" Flask app goes in the myapp.py file:


Next we we take the tutorial Flask-Script manage.py file and adapt it very slightly:

Now we are ready to create a simple migration for a Post model for a blog:

# "python ./manage.py migrate init" does not create the "migrations" directory for me!
mkdir migrations
python ./manage.py migrate create
Name for the migration: Post
Created new migration file: /mypath/migrations/0001_post.py
view raw create.sh hosted with ❤ by GitHub


and you get the template file which looks like this:



In the file put your Post model and modfy "up" and "down":


Our First Migration

python ./manage.py migrate run
view raw run.sh hosted with ❤ by GitHub

Our Second Migration
Now if we want to modify that Post model we can again do:

python ./manage.py migrate create
Name for the migration: Post
Created new migration file: /mypath/migrations/0002_post.py
view raw create.sh hosted with ❤ by GitHub

modify your model and modfy "up" and "down", I've left some comments so you can see what I did:


and run it again.

python ./manage.py migrate run
view raw run.sh hosted with ❤ by GitHub

You should also play around with the "redo" and "undo" commands. That's about it really.

Conclusion
This is only version 0.6 of Flask-Evolution and it's got a way to go, but I can see some use in using it, but it's far from seamless and it's a long way from South.

Documentation is woeful and I'm not convinced the developer Adam Patterson has the time to do the job he'd like to.

You could always offer to give him a hand!

If you see anything wrong with what I've written here or if you spot spelling or other mistakes then please let me know.

Good luck fellow traveller.

Sunday, 8 July 2012

Hosting Domains on Your Domestic Broadband Connection

It's not ideal, but it is possible to host your own domain(s) on your home broadband connection. Find out how.

Hosting on a Budget?
I showed you in my previous last Nginx & uWSGI Living Together in Your Shed how to set up your own Nginx server to serve WSGI applications like Flask, Django, Bottle, Pyramid etc. This allows you to host your own applications on the cheap. All you need is any old server right?

Well sort of. I mean it's cheap enough to buy your own domain name and you probably will want to, but when you are filling in the registration what do you enter when it asks for your DNS servers?

Static IPs can be bought or leased from IP providers and this makes it possible to host your own DNS services. However most of us have dynamic IP addresses at home because our IP providers keep their costs down by buying big blocks of addresses and dynamically allocating us one from the deck each time we need one, and sometimes for their own maintenance reasons too. 

This means your IP address will change from time to time. 

To get around this you can use a dynamic DNS service such as freedns.afraid.org who will point your domain name at your new IP address every time it changes. Cool. Their service is simple, clear and cheap (or even free). I'll let you investigate that yourself, but the main thing is that when you buy your domain name, you need to fill in the DNS bit using the dynamic DNS server names that they provide.

The final thing is: How do you know when your dynamic IP address changes and how do you inform your dynamic DNS service when it happens? Well, for my own purposes I wrote a little script which will do this for you, it checks if your IP has changed and if it has it calls the special callback URL that freedns and others supply you with. 

You can find it here: https://github.com/colwilson/dynamic-dns-updater

Good luck fellow traveller.

Wednesday, 4 July 2012

Nginx & uWSGI Living Together in Your Shed

Let's assume you have just bought the memorable domain name idrinkink.org and you want to host your lovely web app on that old server in the shed. 

I recently set up both Flask-Ahoy! and Django-Ahoy! on a five year old desktop my daughter was chucking out, so I can guarantee you that this configuration can handle enough traffic to get you going, or to demo products to your customers.

Before we start, I'm assuming you are familiar with python web frameworks (Django, Flask, Bottle etc) and with using virtualenv to segregate your environments. I usually use Flask as my framework of choice, so I'm using their "Hello World" app here.

Let's get started:

export CURRENT=i_drink_ink
mkvirtualenv ${CURRENT}
workon ${CURRENT}
cdvirtualenv
pip install Flask uwsgi
touch app.py # the Flask app
touch uwsgi.sh # the uwsgi script that will expose the app
touch idrinkink.org.nginx.conf # the NGinX config to server the app to the greater world
view raw new.sh hosted with ❤ by GitHub
Now the contents of those files:

from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
view raw app.py hosted with ❤ by GitHub
#!/usr/bin/env bash
VIRTUAL_ENV=i_drink_ink
${WORKON_HOME}/${VIRTUAL_ENV}/bin/uwsgi \
--socket /tmp/${VIRTUAL_ENV}.sock \
--chmod-socket \
--pythonpath ${WORKON_HOME}/${VIRTUAL_ENV} \
--module app:app \
--logdate \
--daemonize /tmp/uwsgi-${VIRTUAL_ENV}.log
view raw uwsgi.sh hosted with ❤ by GitHub
server {
listen 80;
server_name www.idrinkink.org idrinkink.org;
location / {
include uwsgi_params;
uwsgi_pass unix:/tmp/i_drink_ink.sock;
}
}
Finally copy the config into place and start the uwsgi daemon and the server up:


# copy nginx config into available slot
cp idrinkink.org.nginx.conf /etc/nginx/sites-available
# link it into the enable slot
ln -s /etc/nginx/sites-available/idrinkink.org.nginx.conf /etc/nginx/sites-enabled/idrinkink.org.nginx.conf
# start uwsgi
chmod 755
${WORKON_HOME}/${VIRTUAL_ENV}/bin/python ./uwsgi.sh
# restart the nginx service
sudo service nginx restart
view raw place.sh hosted with ❤ by GitHub
This of course is just the basics, but it will hopefully give you a starting point from which you can fiddle to your hearts content.

Good luck fellow traveller.

Monday, 2 July 2012

Using Twitter As Your Flask Login Provider in 6 Lines

First off, I lied about the 6 lines, but it got you here and now you can see how simple it is yourself. There are actually 40 lines I think.

When I was building Flask Ahoy! I wanted to use Twitter as the login provider. I could spend a while boring you about why (as opposed to say Google, Facebook, OpenID or Roll-Your-Own), but I'l save that for another exciting post.

I have used the extremely handy Flask-OAuth to do all the legwork so you need to install that:

pip install Flask-OAuth
view raw gistfile1.sh hosted with ❤ by GitHub
Next we need some html for users to click on to sign in and sign out. Try this simple block :

{% block user %}
{% if 'twitter_user' not in session %}
<a href="/login">Sign in with Twitter</a>
{% else %}
<a href="/logout">Sign Out {{session['twitter_user']}}</a>
{% endif %}
{% endblock %}
Next the real code begins. In your views module you need three views:

  • One to send you off to Twitter to get authorized (login)
  • One to get the callback from Twitter and store your authorization credentials (twitter_authorized)
  • One to log you out and tidy up (logout)

from flask import redirect, url_for, session, request, flash, Blueprint, current_app
simple = Blueprint('simple', __name__)
oauth = OAuth()
twitter = twitter_factory(oauth)
@simple.route('/login')
def login():
url = url_for('.twitter_authorized', next=request.args.get('home') or request.referrer or None)
resp = twitter.authorize( callback=url )
return resp
@simple.route('/twitter/authorized')
@twitter.authorized_handler
def twitter_authorized(resp):
next_url = request.args.get('next') or url_for('.index')
if resp is None:
flash(u'You denied the request to sign in.')
return redirect(next_url)
session['twitter_token'] = (
resp['oauth_token'],
resp['oauth_token_secret']
)
session['twitter_user'] = resp['screen_name']
current_app.logger.info(resp)
flash('You were signed in as %s' % resp['screen_name'])
return redirect(next_url)
@simple.route('/logout')
def logout():
session.pop('twitter_user')
return redirect(request.args.get('next') or url_for('.home'))
view raw gistfile1.py hosted with ❤ by GitHub
Finally we need a special little method which remembers your credentials:

@twitter.tokengetter
def get_twitter_oauth_token():
return session.get('oauth_token')
view raw gistfile1.py hosted with ❤ by GitHub

Now for the sake of safety I'm going to point out a couple of things here:

  • This scenario uses flask sessions (encrypted cookies) to store your Twitter OAuth token.
  • When you logout, you are only destroying the twitter_user flag, you should probably destroy your credentials as well.


Good luck fellow travelers.