(Originally posted July 20, 2013)
After having the most basic site, we now want to add a database to the application so we can store the urls that have been uploaded. First we need to do a little refactoring. As it is, our app is just a single file, and that won’t cut it as the code base and functionality grow. The first thing is to move app.py to __init__.py.
1
2
|
$ cp app.py __init__.py $ rm app.py |
That’s fine, but now we’re also going to want to move the actual routes out of __init__.py just to keep things tidy and since we don’t really want app logic in __init__. I’ll include the __init__.py and views.py file in their (relatively small) entirety in a little so there is no confusion.
We also want to make sure that we have room in the directory above to have a script that runs the shell and server.
1
2
3
4
5
6
7
|
from flask.ext.script import Manager, Shell, Server from youtubeparty import app manager = Manager(app) manager.add_command( 'runserver' ,Server()) manager.add_command( 'shell' , Shell()) manager.run() |
To be able to run this, you need
1
|
$ pip install Flask-Script |
This should allow you to run the app now. So the file system now is
youtubeparty/
manage.py
youtubeparty/
__init__.py
templates/
static/
Now we want to add a database to the app. The first step is to download Flask-SQLAlchemy, the most widely used ORM. We’re going to use this because of how large the community is, as well as the fact that it allows connections to many different databases. Make sure your virtualenv is activated, and
1
|
$ pip install Flask-SQLAlchemy |
Now we want to create a simple models.py in the same directory as the __init__.py which has the app in it. Here is what models.py looks like
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
from youtubeparty import app from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy(app) class YTUrl(db.Model): id = db.Column(db.Integer, primary_key = True ) url = db.Column(db.String( 80 )) def __init__( self , url): self .url = url def __repr__( self ): return self .url db.create_all() |
Line 2 at the top actually finds __init__.py and imports from there. This part is a little confusing, so I’m going to include the entire __init__.py so there isn’t any confusion.
1
2
3
4
5
6
7
8
|
from flask import Flask app = Flask(__name__) from models import * app.debug = True import youtubeparty.views |
Views.py looks like
1
2
3
4
5
6
7
8
9
10
11
12
|
from youtubeparty import app from flask import Flask, render_template, url_for, request, redirect from models import db, YTUrl @app .route( '/' , methods = [ 'GET' , 'POST' ]) def index(): if request.method = = 'POST' : url = YTUrl(request.form[ 'youtube-url' ]) db.session.add(url) db.session.commit() queue = db.session.query(YTUrl) return render_template( 'index.html' , queue = queue) |
With this setup, you should be able to go to the top level directory, with manage.py, and run
1
|
$ python manage.py runserver |
and see the server start successfully. There should be some extra messages about the database around the standard ‘listening on 5000′ message. This means that the database is connected because of that last line in models.py Now that we have the database (hopefully for you guys) set up, we want to test it out. We should be able to type a string in and see it in the same manner as we had at the end of the last post. This time now, if we stop and restart the server, the data persists!
The next thing we want to do is to check to make sure that the string that was inputted is a valid youtube url. To do that, we want to use the python module, urlparse. After performing the check, the route in views.py becomes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
from youtubeparty import app from flask import Flask, render_template, url_for, request, redirect from models import db, YTUrl import urlparse YOUTUBE_URL = 'www.youtube.com' @app .route( '/' , methods = [ 'GET' , 'POST' ]) def index(): if request.method = = 'POST' : poss_url = request.form[ 'youtube-url' ] parsed_url = urlparse.urlparse(poss_url) if parsed_url[ 1 ] = = YOUTUBE_URL: url = YTUrl(poss_url) db.session.add(url) db.session.commit() queue = db.session.query(YTUrl) return render_template( 'index.html' , queue = queue) |
This is a very naiive approach for more than a few reasons. It doesn’t check to see if the url actually is valid, and just having the url there doesn’t tell the users much about what’s coming next. Both of these issues however require use of the youtube api, so I’ll wait until a later post to go over that.
Hopefully you’re up to date on all this. Email for any questions at all — I like helping people out. Next up, adding real time support, since having to reload would defeat the purpose.