| @ -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']) | |||