Monday 1 October 2012

Flask, MySQL, WTForms & SQLAlchemy that works

Quick 'n dirty Flask, WTForms & SQLAlchemy that works.

database.py
#!/usr/bin/env python
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
import sqlalchemy.interfaces

# Without this, MySQL will silently insert invalid values in the
# database, causing very long debugging sessions in the long run
# source: http://www.enricozini.org/2012/tips/sa-sqlmode-traditional/
class DontBeSilly(sqlalchemy.interfaces.PoolListener):
    def connect(self, dbapi_con, connection_record):
        cur = dbapi_con.cursor()
        cur.execute("SET SESSION sql_mode='TRADITIONAL'")
        cur = None

engine = create_engine('mysql+mysqldb://root:banana@127.0.0.1/testdb?charset=utf8&use_unicode=0', convert_unicode=True, listeners=[DontBeSilly()], echo=True)
db_session = scoped_session(sessionmaker(autocommit=False,autoflush=False,bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()
Base.metadata.create_all(bind=engine)
models.py
#!/usr/bin/env python
from sqlalchemy import Column, Integer, String
from flask_application.database import Base
  
class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    username = Column(String)
    password = Column(String)
    email = Column(String, unique=True)
    country_id = Column(Integer)

    def __init__(self, username=None, password=None, email=None, country_id):
        self.username = username
        self.password = password
        self.email = email
        self.country_id = country_id

    def __repr__(self):
        return '' % (self.username, self.password, self.email, self.country_id)
forms.py
#!/usr/bin/env python
from flask.ext.wtf import Form, TextField, PasswordField, BooleanField, SelectField
from flask.ext.wtf import Required, Email, EqualTo
    
class user_add_form(Form):
    username = TextField('Username', [Required()])
    password = PasswordField('Password', [Required()])
    confirm = PasswordField('Repeat Password', [Required(), EqualTo('password', message='Passwords must match')])
    email = TextField('Email')
    country_id = SelectField(u'Country', choices=[('1', 'UK - United Kingdom')])
template_add_user.html
{% block content %}

{{ form.username }} {{ form.username.label }}

{{ form.password }} {{ form.password.label }}

{{ form.confirm }} {{ form.confirm.label }}

{{ form.country_id }} {{ form.country_id.label }}

{% endblock content %}
view.py
from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for
from flask_application import app
from flask_application.database import db_session
from flask_application.models import User
from flask_application.forms import user_add_form
from werkzeug.security import generate_password_hash, check_password_hash   

@frontend.route('/users/add', methods=['GET','POST'])
def users_add():
    form = manage_user_add_form(request.form, csrf_enabled=False)
    if form.validate_on_submit():
        new_user = User(
                    form.username.data,
                    generate_password_hash(form.password.data),
                    form.email.data,
                    form.country_id.data
                    )
        db_session.add(new_user)
        db_session.commit()
        
    return render_template('template_add_user.html', form=form)