Getting started with Python web development: Setting up the environment
Posted by Barrett Sonntag in MongoDB, Python on February 1, 2013
Python is a fun language. It is easy to read, write, and they have libraries for almost everything. To try and catch up though all at once I am going to go through the process of setting up the new hot stack. I will be going through this setup on my system using Mac OSX 10.8.2, and we’ll use pip and brew for installing our dependancies for this article (What the heck is pip or brew?) as it makes getting setup very easy.
Where we’ll end up:
- Python 2.7
- Separate Python environments using virtualenv to help with development down the road
- Flask micro-framework for the web server, template engine and API development
- MongoDB for our document store using the PyMongo library
- Jinja2 for the front-end template engine, bundled with Flask
- Flask-OpenID for user login
Installing Python
Easiest step, Mac OSX 10.8.2 is already running Python 2.7.2! If you don’t think you have it open up a terminal and type the command python –version. If you don’t it, go download and install it: http://www.python.org/getit/
$ python --version Python 2.7.2 |
Installing virtualenv
Open up your terminal and fire off a this command to install virtualenv, you may have to use sudo to elevate the command.
$ sudo pip install virtualenv |
After it is installed make a directory to store and locate any virtual environments you have setup for Python and go into that directory.
$ mkdir virtualenvs $ cd virtualenvs |
To make a new virtual environment is really easy, just type the command virtualenv environmentName and it creates the directory structure for you.
$ virtualenv envTest New python executable in envTest/bin/python Installing setuptools............done. Installing pip...............done. |
Go into that new directory that virtualenv created and you’ll see a full folder structure with Python 2.7 in there for you. This is important, to activate the environment on this terminal only run the command source bin/activate to get into the new virtual environment. Use the command deactiavte to get back out of the virtual environment. Any pip commands we run in here, while active, will install to this virtual environment only instead of the computers global store.
$ source bin/activate (envTest) $ pip install blah (envTest) $ deactivate $ |
Why mess with virtualenv at all?
When you start having multiple projects, on multiple servers, you want your local development environment to match that of the server, including things like different framework versions. Setting up and using virtual environments like this allows you to get in the good habit of knowing what is on your box and available to you, and why you chose what you did.
Installing Flask, PyMongo, and Flask-OpenID
Get back into your virtual environment directory you setup earlier and then lets run the easy pip install commands!
$ source bin/activate (envTest) $ pip install Flask (envTest) $ pip install pymongo (envTest) $ pip install Flask-OpenID (envTest) $ deactivate |
Install MongoDB
I just followed the MongoDB installation instructions and it worked perfectly. Simply type the command brew install mongodb and you’re good to go.
$ brew install mongodb |
Test the environment setup
So now that we have everything installed lets run a test Python script to verify that everything is working as we expected. Open up a new terminal and fire up MongoDB using the command mongod and then run this script after activating your virtual environment on the terminal you are in.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from flask import Flask from pymongo import MongoClient import flask_openid mc = MongoClient() print "PyMongo test: " print mc.database_names() print "flask_openid test: " print flask_openid.COMMON_PROVIDERS["google"] app = Flask(__name__) @app.route('/') def hello_world(): return "Flask is running!" if __name__ == '__main__': app.run() |
You should see a result something like this after running it, which means that each library we installed is working correctly.
(envTest) $ python envTest.py PyMongo test: [u'local'] flask_openid test: https://www.google.com/accounts/o8/id * Running on http://127.0.0.1:5000/ |
Now we’re all setup and ready to code, which is what I think I’ll save for the next post.
Launching the TheKnot.com Search BETA
Posted by Barrett Sonntag in ASP.Net, Data, JavaScript, Mobile Development, Portfolio, Website Analysis on December 24, 2012

My major project of 2012, TheKnot.com Search BETA, launched earlier this month, the morning of December 14th, and it was a journey worth documenting. It began back in May when the company decided to start our own labs or internal incubator groups. One began right away in New York City and the other started a couple weeks later in Austin. I had the opportunity to join the Austin group with a team of developers and product people that I highly respected. I was grinning the whole time with excitement. With the direction that we were independent from the company but had access to the data we sequestered ourselves in a room for a few weeks. Over pots of coffee and pints of beer after work we brainstormed our some good ideas for our brides to find inspiration for their weddings. Our group started out as Judy Galani, Product Strategist, Forrest Andrews and Matt Oehlers, Senior Software Engineers, Erin Bender, Freelance Art Director, and myself as Interactive Media Developer. We “sold” the idea and working prototype to our “investors” by October and it was then time to go from prototype to production.
We had to take the design in house from this point on, but after a fond farewell and thank you to Erin we started to add in more management to the group. It was a greenfield project so our back-end developers Matt and Forrest were excited to push forward into new territories. Within a day or two we were able to deploy projects straight from Visual Studio to the AWS servers, I was blown away. Forrest focused on our MongoDB NoSQL data store and the API that I would later pull all the front-end content from, ASP.NET MVC. Matt worked on massaging the data into Apache Solr and in a matter of days we had an impressive result set coming back for queries.

The front-end technology was built to be a responsive two page website that used a combination ofjQuery and Underscore.js along with HTML and CSS to create a multi-device interface that would be familiar and easy to use. The main grid view uses Masonry to create the Pinterest-esque layout for search results and Underscore.js templates to load in a different layout for different data types. The single page view focuses on a low browser width touch interface to give a very image focused search experience. To combine and minify the page scripts down I used the BundleCollection library in ASP.NET MVC which worked great. There are still a large number of extra scripts on the page but I’ve tried to load them asynchronously and not let them interfere with using the interface immediately.
The site has been up and working great for a few weeks now and launched along side a new look and feel for TheKnot.com. Go take a look, and of course let me know if you find any bugs here or on the feedback tab on the bottom!
Adding Pinterest sharing to your iOS app
Posted by Barrett Sonntag in JavaScript, Mobile Development on May 8, 2012
Update: It looks like this latest version of Pinterest has removed the URL scheme to post directly to the app. I do hope they add it back in with another update.
I’ve been working on a new version of the iOS app, Wedding Dress Look Book by The Knot, and I wanted to add in sharing features for the most popular networks. This a wedding dress browsing and sharing app, it has to be the top three social networks, Facebook, Twitter, and of course, Pinterest. I know that Pinterest doesn’t have a public sharing API yet, but I use there app on my iPhone, and I have a good idea of how it works. For Facebook and Twitter I find out that iOS supports URL Schemes, which allow me to just open an app as I would open Safari. Just change the protocol, http for regular URLs, to the name of the app. I found a site that has a list of all sorts of apps that support this, fb:// for Facebook, twitter:// for the Twitter app etc. Unfortunately they didn’t have Pinterest, but an easy guess of pinterest:// launched the app right away, though I didn’t know of the options, and I still couldn’t find any documentation. I started to think about how the Pin It bookmark works, the URL scheme must be inside that JavaScript file that Pinterest loads onto the site in mobile Safari. After running the file, http://passets-cdn.pinterest.com/js/pinmarklet.js, through a Javascript Beautifier we can see Pinterest developers speak lolcat with plenty of hazSite and hazIOS. That was it!
51 52 53 54 55 56 | if (a.v.hazIOS) { a.w.setTimeout(function () { a.w.location = "pinit12://" + e }, 25); a.w.location = "http://" + e } else a.w.open("http://" + e, "pin" + f, a.a.pop) |
Pinterest’s URL scheme is pinit12, I’m guessing 12 is a version number. A little more digging around and I came up with a list of working parameters.
URL Scheme: pinit12://pinterest.com/pin/create/bookmarklet/?
- media: a direct link to the image or I think an encoded image (base64?)
- url: the URL of the source website where the image was found
- description: 500 characters max
- is_video: self describing
Since this code isn’t officially supported it is subject to change, and thankfully there is a way to future proof your app from having a broken link. You are able to check if a URL can be opened without actually opening it in iOS. The trick then is prepping your URL, seeing if it can be opening, and only then displaying the option to share with Pinterest. Using a UIActionSheet, with ARC enabled, this is what I came up with.
int count = 1; UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"" delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:@"Email", nil]; NSString *post = [NSString stringWithFormat:@"pinit12://pin/create/bookmarklet/?media=%@",@"http://yourdomain.com/yourimage.jpg"]; NSString *escapedStringURL = [post stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSURL *url = [NSURL URLWithString:escapedStringURL]; if ([[UIApplication sharedApplication] canOpenURL:url]) { [sheet addButtonWithTitle:@"Pinterest"]; ++count; } [sheet addButtonWithTitle:@"Cancel"]; [sheet setCancelButtonIndex:count]; |
This way, in case the URL scheme changes from pinit12 in the future it won’t break your application.
It has been added as a URL scheme to http://wiki.akosma.com/IPhone_URL_Schemes, most links seem to hit that listing. Thanks @akosmasoftware!