Pro Tip: Install and Uninstalling Flask-SQLAlchemy

Install:

pip install Flask-SQLAlchemy

Uninstall:

pip uninstall Flask-SQLAlchemy

Install Flask-SQLAlchemy to form an abstraction layer between a database (e.g., MySQL, PostgreSQL, SQLite) and Python. SQLAlchemy allows querying a database with Python code as opposed to SQL. Read the SQLAlquemy’s Object Relational Mapping tutorial for usage and syntax details.

$ pip install flask-sqlalchemy

This is the directory structure for a Flask python package as well as how to import each module:

./
└── Appname/
        ├── runserver.py          #import appname.runserver
        └── appname/              #folder contains '__init__.py' so this is the package name
                ├── __init__.py   #import appname
                ├── static/
                │       ├── css/
                │       ├── img/
                │       └──  js/
                ├── templates/
                │       ├── index.htm
                │       ├── login.htm
                │       ├── registration
                │       └── file-a.htm
                │
                ├── views.py     #import appname.views
                ├── file_1.py    #import appname.file_1
                ├── file_n.py    #import appname.file_n
                ├── models.py    #import appname.model
                └── README.md

runserver.py facilitates package creation with Flask by allowing us to use multiple modules with the Flask framework.

from appname import app  #http://flask.pocoo.org/docs/0.10/patterns/packages/#simple-packages
 
app.run(debug=True)

Tells Python to treat our folder (application) as a package. __init__.py contains application-wide imports and configurations. It also imports View functions (the ones with a route() decorator on top).

from flask import Flask 

app = Flask(__name__) #create a Flask object called 'app'. The __name__ variable is the package name (http://flask.pocoo.org/docs/0.10/api/#application-object)

app.secret_key = 'development key'

app.config["MAIL_SERVER"] = "smtp.gmail.com"
app.config["MAIL_PORT"] = 465
app.config["MAIL_USE_SSL"] = True
app.config["MAIL_USERNAME"] = 'contact@example.com'
app.config["MAIL_PASSWORD"] = 'password

from views import mail
mail.init_app(app)

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:password@localhost/db_name'
 
from models import db
db.init_app(app)

import appname.views #always at the bottom of your file. See "circular imports"
from appname import app # which is in  __init__.py See "circular imports"
from flask import render_template, request, flash, session, url_for, redirect
from forms import ContactForm, SignupForm, SigninForm
from flask.ext.mail import Message, Mail
from models import db, User

mail = Mail()

@app.route('/')
def home():
  return render_template('home.html')

@app.route('/about')
def about():
  return render_template('about.html')

@app.route('/contact', methods=['GET', 'POST'])
def contact():
  form = ContactForm()

  if request.method == 'POST':
    if form.validate() == False:
      flash('All fields are required.')
      return render_template('contact.html', form=form)
    else:
      msg = Message(form.subject.data, sender='contact@example.com', recipients=['your_email@example.com'])
      msg.body = """
      From: %s <%s>
      %s
      """ % (form.name.data, form.email.data, form.message.data)
      mail.send(msg)

      return render_template('contact.html', success=True)

  elif request.method == 'GET':
    return render_template('contact.html', form=form)

@app.route('/signup', methods=['GET', 'POST'])
def signup():
  form = SignupForm()

  if 'email' in session:
    return redirect(url_for('profile')) 
  
  if request.method == 'POST':
    if form.validate() == False:
      return render_template('signup.html', form=form)
    else:
      newuser = User(form.firstname.data, form.lastname.data, form.email.data, form.password.data)
      db.session.add(newuser)
      db.session.commit()
      
      session['email'] = newuser.email
      return redirect(url_for('profile'))
  
  elif request.method == 'GET':
    return render_template('signup.html', form=form)

@app.route('/profile')
def profile():

  if 'email' not in session:
    return redirect(url_for('signin'))

  user = User.query.filter_by(email = session['email']).first()

  if user is None:
    return redirect(url_for('signin'))
  else:
    return render_template('profile.html')

@app.route('/signin', methods=['GET', 'POST'])
def signin():
  form = SigninForm()

  if 'email' in session:
    return redirect(url_for('profile')) 
      
  if request.method == 'POST':
    if form.validate() == False:
      return render_template('signin.html', form=form)
    else:
      session['email'] = form.email.data
      return redirect(url_for('profile'))
                
  elif request.method == 'GET':
    return render_template('signin.html', form=form)

@app.route('/signout')
def signout():

  if 'email' not in session:
    return redirect(url_for('signin'))
    
  session.pop('email', None)
  return redirect(url_for('home'))
from flask.ext.sqlalchemy import SQLAlchemy
from werkzeug import generate_password_hash, check_password_hash

db = SQLAlchemy()

class User(db.Model):
  __tablename__ = 'users'
  uid = db.Column(db.Integer, primary_key = True)
  firstname = db.Column(db.String(100))
  lastname = db.Column(db.String(100))
  email = db.Column(db.String(120), unique=True)
  pwdhash = db.Column(db.String(54))
  
  def __init__(self, firstname, lastname, email, password):
    self.firstname = firstname.title()
    self.lastname = lastname.title()
    self.email = email.lower()
    self.set_password(password)
    
  def set_password(self, password):
    self.pwdhash = generate_password_hash(password)
  
  def check_password(self, password):
    return check_password_hash(self.pwdhash, password)