Commits

Anonymous committed 72a47e4

moved away from GAE

Comments (0)

Files changed (14)

-Google App Engine project for keeping food diary when following the Food Opimising programme.
+Project for keeping food diary when following the Food Opimising programme.
 
 Features include:
 
-from google.appengine.ext.webapp.util import run_wsgi_app
+import settings
 
-from foodoptimizr import app
+from foodoptimizr import create_app
 
-run_wsgi_app(app)
+app = create_app(settings)
+
+if __name__ == "__main__":
+    app.run(debug=True)

app.yaml

-application: foodoptimizr
-version: 1
-runtime: python
-api_version: 1
-
-handlers:
-- url: .*
-  script: app.py

foodoptimizr/__init__.py

-import settings
 
-from flask import Flask, g, render_template, request
-from google.appengine.api import users
+from flask import Flask, g, session
 
-from .views import main
+from foodoptimizr import views
+from foodoptimizr.models import User, db
 
-app = Flask(__name__)
-app.config.from_object(settings)
-app.register_module(main)
+DEBUG = True
+SQLALCHEMY_DATABASE_URI = "sqlite:///foodoptimizer.db"
+SQLALCHEMY_ECHO = True
 
-@app.before_request
-def authenticate():
-    g.user = users.get_current_user()
+def create_app(settings=None):
+
+    app = Flask(__name__)
+    if settings:
+        app.config.from_object(settings)
+
+    @app.before_request
+    def authenticate():
+        g.user = None
+        if 'user_id' in session:
+            g.user = User.query.get(session['user_id'])
+
+    app.register_module(views.main)
+    app.register_module(views.auth)
+
+    return app
+
     
-    if not g.user:
-        login_url = users.create_login_url(request.path)
-        return render_template("login.html", login_url=login_url)
 
 
 
-
-
-

foodoptimizr/decorators.py

+import functools
+
+from flask import flash, g, redirect, url_for, request
+
+def login_required(func):
+    """
+    If user is not logged in, redirects user to login page.
+    """
+
+    @functools.wraps(func)
+    def decorate(*args, **kwargs):
+        if g.user:
+            return func(*args, **kwargs)
+
+        flash("You must be logged in to view this page")
+        return redirect(url_for("auth.login", next=request.url))
+    return decorate
+

foodoptimizr/forms.py

+from flaskext.wtf import Form, TextField, PasswordField, SubmitField, \
+        required
+
+
+class LoginForm(Form):
+
+    login = TextField("Username or email address", validators=[required()])
+    password = PasswordField("Password", validators=[required()])
+
+
+class SignupForm(Form):
+
+    pass

foodoptimizr/models.py

+from datetime import datetime
+
+from flaskext.sqlalchemy import SQLAlchemy, BaseQuery
+
+db = SQLAlchemy()
+
+class UserQuery(BaseQuery):
+
+    def authenticate(self, login, password):
+
+        user = self.filter(db.or_(User.username==login,
+                                  User.email==login)).first()
+
+        if user and user.check_password:
+            return user
+
+
+class User(db.Model):
+
+    __tablename__ = "users"
+
+    query_class = UserQuery
+
+    id = db.Column(db.Integer, primary_key=True)
+    username = db.Column(db.Unicode(30), unique=True)
+    email = db.Column(db.String(200), unique=True)
+    joined_on = db.Column(db.DateTime, default=datetime.utcnow)
+    weight = db.Column(db.Float)
+    current_limit = db.Column(db.Integer, default=0)
+    daily_limit_set_on = db.Column(db.DateTime)
+
+    _password = db.Column('password', db.String(800))
+
+    def _set_password(self, password):
+        self._password = generate_password_hash(password)
+
+    def _get_password(self):
+        return self._password
+
+    def check_password(self, password):
+        return self.check_password_hash(self.password, password)
+
+
+class Item(db.Model):
+
+    __tablename__ = "items"
+
+    id = db.Column(db.Integer, primary_key=True)
+    description = db.Column(db.UnicodeText)
+    green_sins = db.Column(db.Float, default=0)
+    red_sins = db.Column(db.Float, default=0)
+    healthy_extra_a = db.Column(db.Boolean, default=False)
+    healthy_extra_b_green = db.Column(db.Boolean, default=False)
+    healthy_extra_b_red = db.Column(db.Boolean, default=False)
+
+    _taglist = db.Column("tags", db.UnicodeText)
+
+
+class Entry(db.Model):
+
+    __tablename__ = "entries"
+
+    id = db.Column(db.Integer, primary_key=True)
+    user_id = db.Column(db.Integer, db.ForeignKey(User.id))
+    item_id = db.Column(db.Integer, db.ForeignKey(Item.id))
+    entered_on = db.Column(db.DateTime, default=datetime.utcnow)
+    qty = db.Column(db.Integer, default=1)
+    
+    user = db.relation(User)
+    item = db.relation(Item)
+
+    def calc_num_sins(self, day):
+
+        qty = self.qty
+        healthy_extra = False
+
+        if self.item.healthy_extra_a:
+            healthy_extra = True
+        elif self.item.healthy_extra_b_green and day == "green":
+            healthy_extra = True
+        elif self.item.healthy_extra_b_red and day == "red":
+            healthy_extra = True
+
+        if healthy_extra:
+            qty -= 1
+
+        if day == "red":
+            sins = self.item.red_sins
+        elif day == "green":
+            sins = self.item.green_sins
+
+        return sins * qty
+
+
+

foodoptimizr/views.py

-from flask import Module, render_template
-
-main = Module('views.main')
-
-@main.route("/")
-def index():
-    return render_template("index.html")

foodoptimizr/views/__init__.py

+from .main import main
+from .auth import auth

foodoptimizr/views/acct.py

Empty file added.

foodoptimizr/views/auth.py

+from flask import Module, render_template, session, redirect, url_for, flash
+
+from foodoptimizr.forms import LoginForm, SignupForm
+from foodoptimizr.models import User, db
+
+auth = Module(__name__)
+
+@auth.route("/login/")
+def login():
+
+    form = LoginForm(next=request.args.get('next'))
+
+    if form.validate_on_submit():
+        
+        user = User.query.authenticate(form.login, form.password)
+        if user:
+
+            session['user_id'] = user.id
+            flash("Welcome back, %s" % user.username)
+
+            next_url = form.next or url_for('main.index')
+
+            return redirect(next_url)
+
+    return render_template("login.html", form=form)
+
+
+@auth.route("/signup/")
+def signup():
+
+    form = SignupForm(next=request.args.get("next"))
+
+    if form.validate_on_submit():
+
+        user = User()
+        form.populate_obj(user)
+
+        db.session.add(user)
+        db.session.commit()
+
+        flash("Welcome, %s" % user.username)
+
+        next_url = form.next or url_for('main.index')
+        return redirect(next_url)
+
+    return render_template("signup.html", form=form)

foodoptimizr/views/login.py

Empty file added.

foodoptimizr/views/main.py

+from flask import Module, render_template
+
+main = Module(__name__)
+
+@main.route("/")
+def index():
+    return render_template("index.html")
+
+
+
+from flaskext.testing import TestCase
+
+from foodoptimizr import create_app
+from foodoptimizr.models import db, Item
+
+class Base(TestCase):
+
+    SQLALCHEMY_DATABASE_URI = "sqlite://"
+    SQLALCHEMY_ECHO = False
+    TESTING = True
+    CSRF_ENABLED = False
+
+    def create_app(self):
+        return create_app(self)
+
+    def setUp(self):
+        db.create_all()
+
+    def tearDown(self):
+        db.session.remove()
+        db.drop_all()
+
+
+class TestEntry(Base):
+
+    def create_item(self, **kwargs):
+
+        return Item(description="20g cheese", **kwargs)
+                    
+    def test_calc_num_sins_red_day_red_item(self):
+
+        item = create_item(healthy_extra_a=True, red_sins=4.5)
+        entry = Entry(item=item, qty=1)
+        assert entry.calc_num_sins("red") == 0
+
+    def test_calc_num_sins_red_day_green_item(self):
+
+        item = create_item(healthy_extra_a=True, green_sins=4.5)
+        entry = Entry(item=item, qty=1)
+        assert entry.calc_num_sins("red") == 4.5
+
+    def test_calc_num_sins_green_day_red_item(self):
+
+        item = create_item(healthy_extra_a=True, red_sins=4.5)
+        entry = Entry(item=item, qty=1)
+        assert entry.calc_num_sins("green") == 4.5
+
+    def test_calc_num_sins_green_day_green_item(self):
+
+        item = create_item(healthy_extra_a=True, green_sins=4.5)
+        entry = Entry(item=item, qty=1)
+        assert entry.calc_num_sins("green") == 0
+
+    def test_calc_num_sins_red_day_green_item_with_healthy_extra_a(self):
+
+        item = create_item(healthy_extra_a=True, green_sins=4.5)
+        entry = Entry(item=item, qty=1)
+        assert entry.calc_num_sins("red") == 0
+
+    def test_calc_num_sins_red_day_red_item_with_healthy_extra_a(self):
+
+        item = create_item(healthy_extra_a=True, red_sins=4.5)
+        entry = Entry(item=item, qty=1)
+        assert entry.calc_num_sins("red") == 0
+