Richard Bucker

Flask, Pystache and Bootstrap

Posted at — Jan 18, 2012

[Update 2012-05-14] RDO pointed out that there were some changes in pystache. The first and foremost is that they changed the API structure entirely. While I might not have actually implemented that best practices as there are a number of ways to accomplish the same thing. I was more interested in staying try to the initial project structure.  So if you read the pystache Renderer class you’ll probably see everything you need. And to round the changes out I found a few bugs in the MANIFEST.in and init.py that have been corrected here. This code runs although it’s not loading any of the images and some of the css… as I have not updated the html to work the way it should. But it’s easy enough for the reader now that the rest is working. (One final note, edit the fluid.html file and change ../assets/ to /static/) I’m using flask, pystache and bootstrap in order to build a fast prototype. I’ve already written a little about this but the text was getting long in the tooth so I cut it off short of a complete description. I decided to break the work into a separate text… as it’s more manageable. Some of these instructions will vary if you are using virtualenv.- download bootstrapcd ${HOME}mkdir -p gitcd ${HOME}/gitgit clone https://github.com/twitter/bootstrap.git- download the latest pystatche (pip does not have the latest code so go to github for it)cd ${HOME}mkdir -p gitcd ${HOME}/gitgit clone https://github.com/defunkt/pystache.gitcd pystachesudo python ./setup.py install- download and install flasksudo pip install flask- download and install ‘modern-package-template’sudo pip install modern-package-template- create your project (answer the questions as best as you can)cd ${HOME}mkdir -p hgcd ${HOME}/hgpaster create -t modern_package helloworld- now you need to do a number of things in order to get pystache to work with bootstrap. I’m going to list them out and give examples where I can. copy the ‘examples’ directory from bootstrap to the ‘src/helloworld’ directory create a ‘static’ directory in the ‘src/helloworld’ directory copy the css and JS directory from the bootstrap directory to the static folder update the MANIFEST.in file to include the examples and static directories update src/helloworld/init.py update src/helloworld/hello.pyFILE: src/helloworld/init.pyfrom helloworld import hellodef main():    hello.main()FILE: src/helloworld/hello.pyfrom pystache.loader import Loaderfrom pystache.renderer import Rendererfrom flask import Flask, url_forapp = Flask(name)@app.route("/simple")def simple(): loader = Loader(extension=‘html’, search_dirs=[app.root_path+'/examples',]) template = loader.load_name(‘fluid’) renderer = Renderer() return renderer.render(template, {‘person’: ‘Mom’})def main(): app.debug = True app.run()FILE: MANIFEST.ininclude README.rstinclude NEWS.txtrecursive-include src/helloworld/examples *recursive-include src/helloworld/static *pystache is able to locate the templates stored in the source because I added the code ‘app.root_path’ to the template directory parameter in the pystache loader.Flask is able to locate the static files because flask defaults ‘/static’ to the folder in the same directory as the current module. This did not require any special config. If you decided to move the file you would have to add some params to app.run()Finally, since setuptools does not really recognize this project structure you have yo update the MANIFEST file yourself in order to tell setuptools to package the example/templates and static files.One parting note. Jinga2 is installed with flask as part of the dependencies. I would have used Jinga2 but except for 2 reasons. 1) I’m experimenting with different languages and I’d rather use one template assembler. 2) There has been some recent criticism of template assemblers in general. The complaint is that they break the MVC model. It is currently impossible for Mustache to do that with the current syntax.Serving any object like JS or PNG files need to be in the static directory or they need to be served by a web gateway in front of the flask instance. Like nginx, lighted or Apache.I hope this article is better than the previous. I might clean that one up.