Skip to content

Commit

Permalink
Initializing - created everything
Browse files Browse the repository at this point in the history
Flask-python and RethinkDB based recipes app
  • Loading branch information
z3ugma committed Jan 4, 2015
0 parents commit 8e5f99d
Show file tree
Hide file tree
Showing 7 changed files with 434 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.pyc
.vagrant
38 changes: 38 additions & 0 deletions Vagrantfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "hashicorp/precise64"

dirname = File.basename(Dir.getwd)
config.vm.hostname = dirname

config.vm.network "forwarded_port", guest: 5000, host: 5005
config.vm.network "forwarded_port", guest: 8080, host: 8085

$script = <<SCRIPT
echo "Provisioning Flask, RethinkDB, Python imaging libraries"
sudo apt-get update
sudo apt-get -y install python avahi-daemon python-pip git curl upstart python-dev build-essential libjpeg-dev libfreetype6-dev zlib1g-dev libpng12-dev
sudo ln -s /usr/lib/x86_64-linux-gnu/libjpeg.so /usr/lib
sudo ln -s /usr/lib/x86_64-linux-gnu/libfreetype.so /usr/lib
sudo ln -s /usr/lib/x86_64-linux-gnu/libz.so /usr/lib
source /etc/lsb-release && echo "deb http://download.rethinkdb.com/apt $DISTRIB_CODENAME main" | sudo tee /etc/apt/sources.list.d/rethinkdb.list
wget -qO- http://download.rethinkdb.com/apt/pubkey.gpg | sudo apt-key add -
sudo apt-get update
sudo apt-get -y install rethinkdb
sudo pip install PIL --upgrade
sudo pip install -r /vagrant/requirements.txt
sudo initctl emit vagrant-ready
SCRIPT

config.vm.provision "shell", inline: $script

end
1 change: 1 addition & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import requests
169 changes: 169 additions & 0 deletions colorpicker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
from collections import namedtuple
from math import sqrt
import random
try:
import Image
except ImportError:
from PIL import Image
import json
import colorsys
import colorific
import urllib2
import urllib, cStringIO
import re
import translitcodec



def get_gimages(query):
answer = []
for i in range(0,8,4):
url = 'https://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=%s&start=%d&imgsz=large&imgtype=photo' % (query,i)
r = urllib2.urlopen(url)
for k in json.loads(r.read())['responseData']['results']:
answer.append(k['tbUrl'])
return answer

def chunks(l, n):
""" Yield successive n-sized chunks from l.
"""
for i in xrange(0, len(l), n):
yield l[i:i+n]

## Slug functions ##

_punct_re = re.compile(r'[\t !"#$%&\()*\-/<=>?@\[\\\]^_`{|},.]+')

def slugify(text, delim=u'-'):
"""Generates an ASCII-only slug."""
result = []
for word in _punct_re.split(text.lower()):
word = word.replace('\'', '') #Don't replace apostrophes with a dash, just strip them
word = word.encode('translit/long')
if word:
result.append(word)
return unicode(delim.join(result))

from flask.ext.wtf import Form
from wtforms.fields import TextField
from wtforms.validators import Required
from wtforms.fields import StringField
from wtforms.widgets import TextArea

class RecipeForm(Form):
title = TextField('title', validators = [Required()])
ingredients = StringField(u'Ingredients', widget=TextArea(),validators = [Required()])
directions = StringField(u'directions', widget=TextArea(), validators = [Required()])


from flask import *
app = Flask(__name__)
app.secret_key = 'correcthorsebatterystaples'

# rethink imports
import rethinkdb as r
from rethinkdb.errors import RqlRuntimeError, RqlDriverError

# rethink config
RDB_HOST = 'localhost'
RDB_PORT = 28015
TODO_DB = 'recipes'

# db setup; only run once
def dbSetup():
connection = r.connect(host=RDB_HOST, port=RDB_PORT)
try:
r.db_create(TODO_DB).run(connection)
r.db(TODO_DB).table_create('recipes').run(connection)
print 'Database setup completed'
except RqlRuntimeError:
print 'Database already exists.'
finally:
connection.close()
dbSetup()

# open connection before each request
@app.before_request
def before_request():
try:
g.rdb_conn = r.connect(host=RDB_HOST, port=RDB_PORT, db=TODO_DB)
except RqlDriverError:
abort(503, "Database connection could be established.")

# close the connection after each request
@app.teardown_request
def teardown_request(exception):
try:
g.rdb_conn.close()
except AttributeError:
pass


@app.route('/favicon.ico')
def favicon():
abort(404)

@app.route('/add', methods = ['GET', 'POST'])
def add():
form = RecipeForm()
#form.ingredients.data = "1c ingredient\nenter ingredients here "

if request.method == 'POST' and form.validate():

lightness = []
rainbow = []
resp=[]
urls = get_gimages("+".join(form.title.data.split()))
for url in urls:
i = cStringIO.StringIO(urllib.urlopen(url).read())
quiche = colorific.extract_colors(i, max_colors=5)
resp.extend([each.value for each in quiche.colors])
resp = [(m,sqrt(0.299 * m[0]**2 + 0.587 * m[1]**2 + 0.114 * m[2]**2)) for m in resp]
lightness = sorted(resp,key=lambda x: x[1])
lightness = [i[0] for i in lightness]
lightness.sort(key=lambda tup: colorsys.rgb_to_hsv(tup[0],tup[1],tup[2])[2])
for each in chunks(lightness,10):
avg = tuple(map(lambda y: sum(y) / len(y), zip(*each)))
rainbow.append(avg)

slug = slugify(form.title.data)

recipe = { 'title': form.title.data, 'ingredients': [{'amount': " ".join(ingredient.split()[0:2]), 'what': " ".join(ingredient.split()[2:])} for ingredient in form.ingredients.data.split('\r\n')], 'directions': form.directions.data.split('\r\n'), 'urls': urls, 'slug': slug, 'avgcolors': [list(i) for i in rainbow]}



recipe['ingredients'] = [i for i in recipe['ingredients'] if not i['what']=='']
recipe['directions'] = [i for i in recipe['directions'] if not i=='']

r.table('recipes').insert(recipe).run(g.rdb_conn)

return redirect(url_for('index', query=slug))


#r.table('recipes').get('de670bed-791d-41d0-97cb-1ceaf9ba54ac').update({'time_updated': r.now(), 'slug': "broccoli-cheese-soup", 'urls': urls, 'avgcolors': [list(i) for i in rainbow]}).run(g.rdb_conn)

return render_template("add.html", form=form)


@app.route('/<query>')
def index(query):
recipe = list(r.table('recipes').filter({'slug': query}).run(g.rdb_conn))

if recipe:
recipe = recipe[0]
else:
abort(404)

steps = []
for i in recipe['directions']:
for j in [k['what'].split(",")[0] for k in recipe['ingredients']]:
i = i.replace(j, ("<kbd>" + j + "</kbd>"))
steps.append(Markup(i))

rainbow = [tuple(l) for l in recipe['avgcolors']]

return render_template("index.html", urls = recipe['urls'], avg=rainbow, ingredients = recipe['ingredients'], steps = steps, title=recipe['title'])


if __name__ == '__main__':
app.run(debug = True, host='0.0.0.0')
5 changes: 5 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
flask
rethinkdb
colorific
translitcodec
flask-wtf
88 changes: 88 additions & 0 deletions templates/add.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Add a Recipe</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.js"></script>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"></style>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>

<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css">


<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Ubuntu">

<style>
body {
font-family: 'Ubuntu', serif;

}
textarea {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
height:100%;
}
</style>
</head>
<body>
<div class="container">


<form action="" role="form" method="POST" name="add_task">
{{form.hidden_tag()}}

<div class="row">
<div class="col-md-12">
<h1>Add a Recipe</h1>

<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"></h3>Title
</div>
<div class="panel-body">
{{form.title}}
</div>
</div>
</div>

</div>
<div class="row">

<div class="col-md-3">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"></h3>Ingredients
</div>
<div class="panel-body" >
{{ form.ingredients(rows="10") }}
</div>
</div>
</div>
<div class="col-md-9">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"></h3> Directions </h3>
</div>
<div class="panel-body">
{{ form.directions(rows="10") }}
</div>
</div>
</div>

<input type="submit" value="Add Recipe" class="btn btn-default btn-md">
{% for error in form.errors.label %}
<span style="color: red;">{{ error }}</span>
{% endfor %}
</div>

</form>
</div>



</body>
</html>
Loading

0 comments on commit 8e5f99d

Please sign in to comment.