-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() | ||
|
||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
miguelgrinberg
Author
Owner
|
||
|
||
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 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from flask import Blueprint | ||
|
||
main = Blueprint('main', __name__) | ||
|
||
from . import views, errors |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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') |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
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 | ||
return redirect(url_for('.index')) | ||
return render_template('index.html', | ||
form=form, name=session.get('name'), | ||
known=session.get('known', False)) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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.googlemail.com') | ||
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 <[email protected]>' | ||
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 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import os | ||
import click | ||
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() | ||
@click.argument('test_names', nargs=-1) | ||
def test(test_names): | ||
"""Run the unit tests.""" | ||
import unittest | ||
if test_names: | ||
tests = unittest.TestLoader().loadTestsFromNames(test_names) | ||
else: | ||
tests = unittest.TestLoader().discover('tests') | ||
unittest.TextTestRunner(verbosity=2).run(tests) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
alembic==0.9.3 | ||
blinker==1.4 | ||
click==6.7 | ||
dominate==2.3.1 | ||
Flask==0.12.2 | ||
Flask-Bootstrap==3.3.7.1 | ||
Flask-Mail==0.9.1 | ||
Flask-Migrate==2.0.4 | ||
Flask-Moment==0.5.1 | ||
Flask-SQLAlchemy==2.2 | ||
Flask-WTF==0.14.2 | ||
itsdangerous==0.24 | ||
Jinja2==2.9.6 | ||
Mako==1.0.7 | ||
MarkupSafe==1.0 | ||
python-dateutil==2.6.1 | ||
python-editor==1.0.3 | ||
six==1.10.0 | ||
SQLAlchemy==1.1.11 | ||
visitor==0.1.3 | ||
Werkzeug==0.12.2 | ||
WTForms==2.1 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import unittest | ||
from flask import current_app | ||
from app import create_app, db | ||
|
||
|
||
class BasicsTestCase(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']) |
7 comments
on commit fb13ded
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Miguel,
It appears that i can't run the test individually :
`test_app_is_testing (unittest.loader._FailedTest) ... ERROR
======================================================================
ERROR: test_app_is_testing (unittest.loader._FailedTest)
ImportError: Failed to import test module: test_app_is_testing
Traceback (most recent call last):
File "/usr/local/Cellar/python/3.7.4/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/loader.py", line 154, in loadTestsFromName
module = import(module_name)
ModuleNotFoundError: No module named 'test_app_is_testing'
Ran 1 test in 0.001s
FAILED (errors=1)`
Any idea ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pdamoune what command are you using for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't see any code to run the app, and when I use 'python flasky.py test', there is no reaction
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@LinzzMichael do you have the book? This repo is not a standalone application, it is a teaching application that you have to follow using the instructions in the book. In any case, flask apps these days are started with the flask
command.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@miguelgrinberg yes,I had follow the book to write my code, but I got the error "discover() missing 1 required positional argument: 'start_dir' ", so I decide to try the example code, but I find it's different from the book, I am not quite understand the example, dose it mean it can't not run?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you are using the first edition of the book? This code is for the 2nd edition, first edition is here: https://github.com/miguelgrinberg/flasky-first-edition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@miguelgrinberg Thank you very much for answer my question! your book is pretty good, May be I need to buy the new book.
in the 2016 pycon presentation(Flask at Scale) you said that we need to do "from . import model" so that they are registered with SQLAlchemy. that's not the case anymore?