
Programmer
Freelancer
Code Demigod
Resume
Contact me
tg-admin quickstart -sThe -s flag is used to siginify that we will use SQLAlchemy instead of the default SQLObject. During the execution of the command, you will be asked for the project name and package name and if you would like identity functionality in this project. Name the project moviestg, as well as the package, and answer no for the identity part. In this project, we will not use it. Next, let's just check that the generated application works correctly. Go inside the project directory moviestg and execute the following commands:
start-moviestg.pyAfter the command finishes execution, visit the address "localhost:8080" and you should see the welcome page. Next, we need to create our model. TG takes care of creating the tables we need in the database if we just go ahead and define the model as a Python class in the model.py file in moviestg/moviestg/model.py. The quickstart project has all the proper imports, so we just need to define our model.
movie_table = Table('movie_table', metadata,
Column('movieid', Integer, primary_key=True),
Column('title', String),
Column('source', String),
Column('thumb', String),
Column('width', Integer),
Column('height', Integer),
)
class Movie(object):
def __repr__(self):
return "Movie %s - %s"%(self.movieid, self.title)
assign_mapper(session.context, Movie, movie_table)
You should read the tutorial on the SQLAlchemy webpage, its very user-friendly. But for a quick hint, this code simply constructs the table along with its corresponding class and associates the two.
To construct the database and corresponding table, execute the following command in the tgmovies directory.
tg-admin sql createNext we create the page to upload the the videos. The template directory is in tgmovies/tgmovies/templates. For now, the default generated templates are Kid templates, so just go ahead and remove all of them from the directory except the __init__.py file. We will create our own genshi template. Create a file called addmovie.html and paste the folowing code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/"> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/> <title>Video Sharing Site</title> </head> <body> <form enctype="multipart/form-data" method="post" action="upload"> <table> <tr><td>Title</td><td><input type="text" name="title"/></td></tr> <tr><td>Movie</td><td><input type="file" name="movie"/></td></tr> </table> <input type="submit" value="Upload" /> </form> </body> </html>Next, we need to edit the controller and implement the glue code between the controller, templates and model. The controller is in the tgmovies/tgmovies directory and is called controllers.py. Replace the imports at the top with the following code, we will need them later on:
from turbogears import controllers, expose, flash from model import * import os import re import string from cherrypy.lib.cptools import serveFileThe only part that should look strange to you is the last line, the cherrypy include. This include gives us the ability to serve files through cherrypy.(HINT: this is for cherrypy 2.2.1, newer releases have changed the path) Replace the index function with the following code:
@expose(template="genshi:moviestg.templates.addmovie")
def index(self):
return dict()
This directs the index method to show the addmovie.html genshi template.
You've seen that we submit the form to the upload address. So now we have to write the upload functionality in the controller.
We've already Imported the string module and re module. and so paste the following methods inside the controller
@expose(template="genshi:moviestg.templates.upload")
def upload(self, title, movie):
#the upload form submits to here and the posted
#fields will be recieved as arguments
uploadedfilename = movie.filename
#get base name(without extension)
#the join part is to take care of files called example.foo.avi for example
basefilename = string.join(re.split("\.", uploadedfilename)[0:-1], ".")
basepath = os.getcwd() + "/"
insertedid = self.preminsert(title)
uploadedfilename = basefilename + str(insertedid) + ".avi"
flvfilename = basefilename + str(insertedid) + ".flv"
thumbnailname = basefilename + str(insertedid) + ".gif"
uploadedfilepath = basepath + uploadedfilename
flvfilepath = basepath + flvfilename
thumbnailpath = basepath + thumbnailname
uploadedfile = file(uploadedfilepath, "wb")
while True:
data = movie.file.read(1024*8)
if not data:
break
uploadedfile.write(data)
uploadedfile.flush()
uploadedfile.close()
self.converttoflv(uploadedfilepath, flvfilepath)
self.getthumbnail(uploadedfilepath, thumbnailpath)
query = session.query(Movie)
insertedmovie = query.get_by(movieid=insertedid)
insertedmovie.source = flvfilepath
insertedmovie.thumb = thumbnailpath
session.flush()
return dict(movieid=str(insertedid))
def converttoflv(self, inpath, outpath):
cmd = "ffmpeg -v 0 -i %s -ar 11025 %s 2>&1"%(inpath, outpath)
os.system(cmd)
def getthumbnail(self, inpath, outpath):
cmd = "ffmpeg -vframes 1 -i %s -pix_fmt rgb24 %s 2>&1"%(inpath, outpath)
os.system(cmd)
def preminsert(self, title):
"""A preliminary insert method so that we can
get the generated id.
Parameters:
title - title for the movie
Return: Generated id
"""
stmnt = movie_table.insert()
res = stmnt.execute(title= title, width=300, height=200)
return res.last_inserted_ids()[0]
This sets the template that will carry the success and generated id of this conversion process. Now we need to create this template. So we create the upload.html template with the following code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/> <title>Video Sharing Site</title> </head> <body> Successfully converted movie with id $movieid </body> </html>Now let's test the application. Start up the server again if you didn't leave it on and upload an avi. Visit http://localhost:8080 and you should see there the upload form. So go ahead and upload an avi file and once this is done, it should re-direct you to another page that informs you of the assigned movie id. Next, we need to create the flex interface. Create and build the simplemovie.mxml in the moviestg directory by compiling the following code with the -use-network=false flag incase you're deploying on your local computer.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:VBox backgroundColor="white" width="400" height="335">
<mx:VideoDisplay width="400" height="300" id="videoPlayer"
source="{Application.application.parameters.movie}" />
<mx:HBox width="100%" horizontalAlign="center">
<mx:Button label="Play" click="videoPlayer.play()" />
</mx:HBox>
</mx:VBox>
</mx:Application>
Now let's create the page that hosts the swf. Copy the following markup into the simptest.html template:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<title>Video Sharing Site</title>
</head>
<body>
<table>
<tr><td valign="top">
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="400" height="335" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
<param name="movie" value="simplemovie" />
<param name="quality" value="high" />
<param name="flashVars" value="movie=showmovie?movieid=$movieid"/>
<embed src="simplemovie" quality="high" width="400" height="335" play="true" loop="false" flashVars="movie=showmovie?movieid=$movieid" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer">
</embed>
</object>
</td>
<td valign="top">
<ul>
<li py:for="movie in movies"><a href="simptest?movieid=${movie.movieid}">${movie.title}</a></li>
</ul>
</td></tr>
</table>
</body>
</html>
Next, we need to create the simplemovie method which would server the swf and the showmovie method which would serve the selected movie for the swf.
Add the following code to the controller:
@expose(template="genshi:moviestg.templates.simptest")
def simptest(self, movieid = None):
query = session.query(Movie)
selectedmovies = query.select()
return dict(movieid = movieid, movies = selectedmovies)
@expose()
def simplemovie(self):
executionpath = os.getcwd()
return serveFile(executionpath + "/simplemovie.swf")
@expose()
def showmovie(self, movieid = None):
if( movieid != None):
query = session.query(Movie)
reqmovie = query.get_by(movieid=movieid)
if(reqmovie != None):
return serveFile(reqmovie.source)
else:
return dict()
else:
return dict()
Now you can go ahead and test the application again. Upload a few more videos, and then visit the simptest address(http://localhost:8080/simptest).
This is enough to show off Python and TurboGears and hopefully get you to consider them in your projects. The original tutorial continues on to show off flex heavily, which would warrant a tutorial on its own. But for the sake of completeness i will complete the tutorial in part2.