Skip to main content

Flask, Pystache and Bootstrap

[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 bootstrap
cd ${HOME}
mkdir -p git
cd ${HOME}/git
git 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 git
cd ${HOME}/git
git clone https://github.com/defunkt/pystache.git
cd pystache
sudo python ./setup.py install

- download and install flask
sudo 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 hg
cd ${HOME}/hg
paster 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.py


FILE: src/helloworld/__init__.py
from helloworld import hello
def main():
    hello.main()

FILE: src/helloworld/hello.py
from pystache.loader import Loader
from pystache.renderer import Renderer
from flask import Flask, url_for

app = 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.in
include README.rst
include NEWS.txt
recursive-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.

Comments

  1. Unfortunately, I think Pystache changed its structure since you wrote this. I don't think it's possible to

    loader = pystache.Loader()
    template = loader.load_template('fluid',
    app.root_path+'/examples',
    extension='html')
    Now you need to pass the path and extension in to the constructor and use load_name or load_object instead.

    ReplyDelete
  2. I have not used Flask all that much but I appreciate the note. I will update my code, libs and test my code again. Thank you; I'll post my results here.

    ReplyDelete
  3. Thanks again for pointing this out. I have corrected the code and I prepended a comment at the top of the article. The changes were minor.

    ReplyDelete
  4. Richard, yes I was surprised as well how much they changed their API structure. I'm sure there's a good reason for such drastic change, but breaking back-wards compatibility set off a bunch of alarms in my head.

    ReplyDelete
  5. Hi, Pystache maintainer here. Thanks for your patience with the changes, and thanks for posting about Pystache.

    The backwards incompatible changes were made because the API had what could be described as some circular dependencies that were hurting the ability to develop and maintain the code. This was noted, for example, here:

    "The real issue is the strange relationship between templates and views. As the comment above indicates, there is a 'loop' between views and templates... Really it's a bad case of tight coupling. Views need templates, and templates need views."

    (from https://github.com/defunkt/pystache/issues/13 )

    On the plus side, huge progress has been made since then over the past six months in terms of adding stability and increased test coverage, fixing bugs, adding features, and expanding supported use cases (Python 3.x, newest version of Mustache spec, robust and consistent unicode/encoding handling, greater configurability, etc). Most of this is described in the project history (with 0.5.3 to come soon as well).

    It was also discussed that such changes shouldn't be forbidden given that Pystache is still on a 0.x version number which in semantic versioning means unstable: http://semver.org/

    By the way, I looked at your sample code above and went ahead and created an issue to add a render_name() method to the Renderer class:

    https://github.com/defunkt/pystache/issues/122

    This is something I've been wanting to add for some time anyways, and seeing your need confirms that. That change should prevent needing to instantiate a Loader manually, and you'd still be able to pass the template extension and search_dirs parameters to the Renderer class directly (which the Renderer class already supports). Thanks again.

    ReplyDelete
  6. Chris, Thanks for the comment; I appreciate your interest. Mustache is a fantastic tool and I use it wherever I can. Having it available on so many languages is a great benefit. Specially now as I'm about to embark on some code generation which I think pystache will be ideally suited for.

    I do not presume to know what all of your challenges are... but it would be interesting if there were a snippet store of some kind. That way I could load up all of my snippets from a config file or maybe some well formed __init__.py or manifest.in file. Certainly this would be an extension that might need to be pushed uphill to the other teams.

    There are a couple of use-cases for pystache. (1) one-off templates and (2) many templates. Anything that is going to make (2) easier.

    Thanks again,

    ReplyDelete
  7. Thanks for the reply, Richard. I'm curious to understand your "snippet" idea a bit more and the use cases you have in mind.

    Re: code generation, I'm coincidentally just about to start publicizing the following project (Groom): http://cjerdonek.github.com/groom/ (along with a corresponding Python implementation).

    It's basically Mustache for project templates (or more broadly, directory structures) along with a way to distribute them. The primary use case I had in mind was project creation or stubbing out new projects. Is that what you meant by code generation?

    ReplyDelete
  8. WOW! Groom has some serious awesomeness potential. People in the business of customizing apps and even one-off could get some serious potential here. just in case there is a +1 instance.

    The first idea I had was based on code generation; something similar to what they describe in "the pragmatic programmer". For example, in order to shortcut the development cycle I created several state-machines in a CSV file (exported from a spreadsheet). The CSV is loaded into memory and the various modules, classes, functions interact with this read-only data. I would prefer to convert or generate the CSV into real code as part of a compile step prior to deploy. Don't get me wrong, the current model works but could be better to debug production issues of the code was fully realized. (I hate META programming). Since the various "states" were well-known it would make sense to simply template the snippets/partials.

    It's possible that the other idea is already implemented. I have not read the pystache code completely. What I'm thinking about is that once the template has been loaded into memory that it's stored in a key/value cache (like redis) that can be accessed the next time that snippet is needed so that the API does not have to go back to disk. One could also argue for a "preload" of the cache so that the first people to access the resources are not starved and there are no rushing hoard issues.

    I hope I'm clear. If not we could take the discussion offline until we hash a complete description.

    ReplyDelete
  9. PS: I passed the link to Groom to an acquaintance of mine that does a lot of code generation. I hope he finds it useful.

    ReplyDelete
  10. Regarding the second part, Pystache lets you pass in a custom partial loader, so if you wanted you could load all the partials into memory and pass them in manually. Version 0.5.3 (not yet released) also lets you "pre-parse" or compile a template. So you'd have the option of compiling all of them in advance and storing them in memory (at least in Python). Also, you're welcome to contact me off-line.

    ReplyDelete

Post a Comment

Popular posts from this blog

Entry level cost for CoreOS+Tectonic

CoreOS and Tectonic start their pricing at 10 servers. Managed CoreOS starts at $1000 per month for those first 10 servers and Tectonic is $5000 for the same 10 servers. Annualized that is $85K or at least one employee depending on your market. As a single employee company I'd rather hire the employee. Specially since I only have 3 servers.

The pricing is biased toward the largest servers with the largest capacities; my dual core 32GB i5 IntelNuc can never be mistaken for a 96-CPU dual or quad core DELL

If CoreOS does not figure out a different barrier of entry they are going to follow the Borland path to obscurity.

UPDATE 2017-10-30: With gratitude the CoreOS team has provided updated information on their pricing, however, I stand by my conclusion that the effective cost is lower when you deploy monster machines. The cost per node of my 1 CPU Intel NUC is the same as a 96 CPU server when you get beyond 10 nodes. I'll also reiterate that while my pricing notes are not currently…

eGalax touch on default Ubuntu 14.04.2 LTS

I have not had success with the touch drivers as yet.  The touch works and evtest also seems to report events, however, I have noticed that the button click is not working and no matter what I do xinput refuses to configure the buttons correctly.  When I downgraded to ubuntu 10.04 LTS everything sort of worked... there must have been something in the kermel as 10.04 was in the 2.6 kernel and 4.04 is in the 3.x branch.

One thing ... all of the documentation pointed to the wrong website or one in Taiwanese. I was finally able to locate the drivers again: http://www.eeti.com.tw/drivers_Linux.html (it would have been nice if they provided the install instructions in text rather than PDF)
Please open the document "EETI_eGTouch_Programming_Guide" under the Guide directory, and follow the Guidline to install driver.
download the appropriate versionunzip the fileread the programming manual And from that I'm distilling to the following: execute the setup.sh answer all of the questio…

Prometheus vs Bosun

In conclusion... while Bosun(B) is still not the ideal monitoring system neither is Prometheus(P).

TL;DR;

I am running Bosun in a Docker container hosted on CoreOS. Fleet service/unit files keep it running. However in once case I have experienced at least one severe crash as a result of a disk full condition. That it is implemented as part golang, java and python is an annoyance. The MIT license is about the only good thing.

I am trying to integrate Prometheus into my pipeline but losing steam fast. The Prometheus design seems to desire that you integrate your own cache inside your application and then allow the server to scrape the data, however, if the interval between scrapes is shorter than the longest transient session of your application then you need a gateway. A place to shuttle your data that will be a little more persistent.

(1) storing the data in my application might get me started more quickly
(2) getting the server to pull the data might be more secure
(3) using a push g…