@ -0,0 +1,28 @@ | |||
from flask import Flask | |||
from flask_bootstrap import Bootstrap | |||
from flask_mail import Mail | |||
from flask_moment import Moment | |||
from flask_sqlalchemy import SQLAlchemy | |||
from config import config | |||
bootstrap = Bootstrap() | |||
mail = Mail() | |||
moment = Moment() | |||
db = SQLAlchemy() | |||
def create_app(config_name): | |||
app = Flask(__name__) | |||
app.config.from_object(config[config_name]) | |||
config[config_name].init_app(app) | |||
bootstrap.init_app(app) | |||
mail.init_app(app) | |||
moment.init_app(app) | |||
db.init_app(app) | |||
from .main import main as main_blueprint | |||
app.register_blueprint(main_blueprint) | |||
return app |
@ -0,0 +1,20 @@ | |||
from threading import Thread | |||
from flask import current_app, render_template | |||
from flask_mail import Message | |||
from . import mail | |||
def send_async_email(app, msg): | |||
with app.app_context(): | |||
mail.send(msg) | |||
def send_email(to, subject, template, **kwargs): | |||
app = current_app._get_current_object() | |||
msg = Message(app.config['FLASKY_MAIL_SUBJECT_PREFIX'] + ' ' + subject, | |||
sender=app.config['FLASKY_MAIL_SENDER'], recipients=[to]) | |||
msg.body = render_template(template + '.txt', **kwargs) | |||
msg.html = render_template(template + '.html', **kwargs) | |||
thr = Thread(target=send_async_email, args=[app, msg]) | |||
thr.start() | |||
return thr |
@ -0,0 +1,7 @@ | |||
from flask import Blueprint | |||
main = Blueprint('main', __name__) | |||
from . import views, errors |
@ -0,0 +1,12 @@ | |||
from flask import render_template | |||
from . import main | |||
@main.app_errorhandler(404) | |||
def page_not_found(e): | |||
return render_template('404.html'), 404 | |||
@main.app_errorhandler(500) | |||
def internal_server_error(e): | |||
return render_template('500.html'), 500 |
@ -0,0 +1,8 @@ | |||
from flask_wtf import FlaskForm | |||
from wtforms import StringField, SubmitField | |||
from wtforms.validators import DataRequired | |||
class NameForm(FlaskForm): | |||
name = StringField('What is your name?', validators=[DataRequired()]) | |||
submit = SubmitField('Submit') |
@ -0,0 +1,29 @@ | |||
from flask import render_template, session, redirect, url_for, current_app | |||
from .. import db | |||
from ..models import User | |||
from ..email import send_email | |||
from . import main | |||
from .forms import NameForm | |||
@main.route('/', methods=['GET', 'POST']) | |||
def index(): | |||
form = NameForm() | |||
if form.validate_on_submit(): | |||
user = User.query.filter_by(username=form.name.data).first() | |||
if user is None: | |||
user = User(username=form.name.data) | |||
db.session.add(user) | |||
db.session.commit() | |||
session['known'] = False | |||
if current_app.config['FLASKY_ADMIN']: | |||
send_email(current_app.config['FLASKY_ADMIN'], 'New user', | |||
'mail/new_user', user=user) | |||
else: | |||
session['known'] = True | |||
session['name'] = form.name.data | |||
form.name.data = '' | |||
return redirect(url_for('.index')) | |||
return render_template('index.html', | |||
form=form, name=session.get('name'), | |||
known=session.get('known', False)) |
@ -0,0 +1,21 @@ | |||
from . import db | |||
class Role(db.Model): | |||
__tablename__ = 'roles' | |||
id = db.Column(db.Integer, primary_key=True) | |||
name = db.Column(db.String(64), unique=True) | |||
users = db.relationship('User', backref='role', lazy='dynamic') | |||
def __repr__(self): | |||
return '<Role %r>' % self.name | |||
class User(db.Model): | |||
__tablename__ = 'users' | |||
id = db.Column(db.Integer, primary_key=True) | |||
username = db.Column(db.String(64), unique=True, index=True) | |||
role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) | |||
def __repr__(self): | |||
return '<User %r>' % self.username |
@ -0,0 +1,46 @@ | |||
import os | |||
basedir = os.path.abspath(os.path.dirname(__file__)) | |||
class Config: | |||
SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard to guess string' | |||
MAIL_SERVER = os.environ.get('MAIL_SERVER', 'smtp.strato.de') | |||
MAIL_PORT = int(os.environ.get('MAIL_PORT', '587')) | |||
MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS', 'true').lower() in \ | |||
['true', 'on', '1'] | |||
MAIL_USERNAME = os.environ.get('MAIL_USERNAME') | |||
MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD') | |||
FLASKY_MAIL_SUBJECT_PREFIX = '[Flasky]' | |||
FLASKY_MAIL_SENDER = 'Flasky Admin <flasky@example.com>' | |||
FLASKY_ADMIN = os.environ.get('FLASKY_ADMIN') | |||
SQLALCHEMY_TRACK_MODIFICATIONS = False | |||
@staticmethod | |||
def init_app(app): | |||
pass | |||
class DevelopmentConfig(Config): | |||
DEBUG = True | |||
SQLALCHEMY_DATABASE_URI = os.environ.get('DEV_DATABASE_URL') or \ | |||
'sqlite:///' + os.path.join(basedir, 'data-dev.sqlite') | |||
class TestingConfig(Config): | |||
TESTING = True | |||
SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL') or \ | |||
'sqlite://' | |||
class ProductionConfig(Config): | |||
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \ | |||
'sqlite:///' + os.path.join(basedir, 'data.sqlite') | |||
config = { | |||
'development': DevelopmentConfig, | |||
'testing': TestingConfig, | |||
'production': ProductionConfig, | |||
'default': DevelopmentConfig | |||
} |
@ -0,0 +1,21 @@ | |||
import os | |||
from flask_migrate import Migrate | |||
from app import create_app, db | |||
from app.models import User, Role | |||
app = create_app(os.getenv('FLASK_CONFIG') or 'default') | |||
migrate = Migrate(app, db) | |||
@app.shell_context_processor | |||
def make_shell_context(): | |||
return dict(db=db, User=User, Role=Role) | |||
@app.cli.command() | |||
def test(): | |||
"""Run the unit tests.""" | |||
import unittest | |||
tests = unittest.TestLoader().discover('tests') | |||
unittest.TextTestRunner(verbosity=2).run(tests) |
@ -1,111 +0,0 @@ | |||
import os | |||
from threading import Thread | |||
from flask import Flask, render_template, session, redirect, url_for | |||
from flask_bootstrap import Bootstrap | |||
from flask_moment import Moment | |||
from flask_wtf import FlaskForm | |||
from wtforms import StringField, SubmitField | |||
from wtforms.validators import DataRequired | |||
from flask_sqlalchemy import SQLAlchemy | |||
from flask_migrate import Migrate | |||
from flask_mail import Mail, Message | |||
basedir = os.path.abspath(os.path.dirname(__file__)) | |||
app = Flask(__name__) | |||
app.config['SECRET_KEY'] = 'hard to guess string' | |||
app.config['SQLALCHEMY_DATABASE_URI'] = \ | |||
'sqlite:///' + os.path.join(basedir, 'data.sqlite') | |||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False | |||
app.config['MAIL_SERVER'] = 'smtp.strato.com' | |||
app.config['MAIL_PORT'] = 587 | |||
app.config['MAIL_USE_TLS'] = True | |||
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME') | |||
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD') | |||
app.config['FLASKY_MAIL_SUBJECT_PREFIX'] = '[Flasky]' | |||
app.config['FLASKY_MAIL_SENDER'] = 'Flasky Admin <flasky@example.com>' | |||
app.config['FLASKY_ADMIN'] = os.environ.get('FLASKY_ADMIN') | |||
bootstrap = Bootstrap(app) | |||
moment = Moment(app) | |||
db = SQLAlchemy(app) | |||
migrate = Migrate(app, db) | |||
mail = Mail(app) | |||
class Role(db.Model): | |||
__tablename__ = 'roles' | |||
id = db.Column(db.Integer, primary_key=True) | |||
name = db.Column(db.String(64), unique=True) | |||
users = db.relationship('User', backref='role', lazy='dynamic') | |||
def __repr__(self): | |||
return '<Role %r>' % self.name | |||
class User(db.Model): | |||
__tablename__ = 'users' | |||
id = db.Column(db.Integer, primary_key=True) | |||
username = db.Column(db.String(64), unique=True, index=True) | |||
role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) | |||
def __repr__(self): | |||
return '<User %r>' % self.username | |||
def send_async_email(app, msg): | |||
with app.app_context(): | |||
mail.send(msg) | |||
def send_email(to, subject, template, **kwargs): | |||
msg = Message(app.config['FLASKY_MAIL_SUBJECT_PREFIX'] + subject, | |||
sender=app.config['FLASKY_MAIL_SENDER'], recipients=[to]) | |||
msg.body = render_template(template + '.txt', **kwargs) | |||
msg.html = render_template(template + '.html', **kwargs) | |||
thr = Thread(target=send_async_email, args=[app, msg]) | |||
thr.start() | |||
return thr | |||
class NameForm(FlaskForm): | |||
name = StringField('What is your name?', validators=[DataRequired()]) | |||
submit = SubmitField('Submit') | |||
@app.shell_context_processor | |||
def make_shell_context(): | |||
return dict(db=db, User=User, Role=Role) | |||
@app.errorhandler(404) | |||
def page_not_found(e): | |||
return render_template('404.html'), 404 | |||
@app.errorhandler(500) | |||
def internal_server_error(e): | |||
return render_template('500.html'), 500 | |||
@app.route('/', methods=['GET', 'POST']) | |||
def index(): | |||
form = NameForm() | |||
if form.validate_on_submit(): | |||
user = User.query.filter_by(username=form.name.data).first() | |||
if user is None: | |||
user = User(username=form.name.data) | |||
db.session.add(user) | |||
db.session.commit() | |||
session['known'] = False | |||
if app.config['FLASKY_ADMIN']: | |||
send_email(app.config['FLASKY_ADMIN'], ' New user', | |||
'mail/new_user', user=user) | |||
else: | |||
session['known'] = True | |||
session['name'] = form.name.data | |||
form.name.data = '' | |||
return redirect(url_for('index')) | |||
return render_template('index.html', form=form, name=session.get('name'), | |||
known=session.get('known', False)) |
@ -0,0 +1,22 @@ | |||
alembic==1.0.1 | |||
blinker==1.4 | |||
Click==7.0 | |||
dominate==2.3.4 | |||
Flask==1.0.2 | |||
Flask-Bootstrap==3.3.7.1 | |||
Flask-Mail==0.9.1 | |||
Flask-Migrate==2.2.1 | |||
Flask-Moment==0.6.0 | |||
Flask-SQLAlchemy==2.3.2 | |||
Flask-WTF==0.14.2 | |||
itsdangerous==0.24 | |||
Jinja2==2.10 | |||
Mako==1.0.7 | |||
MarkupSafe==1.0 | |||
python-dateutil==2.7.3 | |||
python-editor==1.0.3 | |||
six==1.11.0 | |||
SQLAlchemy==1.2.12 | |||
visitor==0.1.3 | |||
Werkzeug==0.14.1 | |||
WTForms==2.2.1 |
@ -0,0 +1,22 @@ | |||
import unittest | |||
from flask import current_app | |||
from app import create_app, db | |||
class BasicTestCase(unittest.TestCase): | |||
def setUp(self): | |||
self.app = create_app('testing') | |||
self.app_context = self.app.app_context() | |||
self.app_context.push() | |||
db.create_all() | |||
def tearDown(self): | |||
db.session.remove() | |||
db.drop_all() | |||
self.app_context.pop() | |||
def test_app_exists(self): | |||
self.assertFalse(current_app is None) | |||
def test_app_is_testing(self): | |||
self.assertTrue(current_app.config['TESTING']) |