refctored project struture, upgraded project dependencoes
parent
f16cd5eff6
commit
d1d41606cd
|
@ -1,3 +1,4 @@
|
|||
.env
|
||||
env
|
||||
venv
|
||||
temp
|
||||
|
|
|
@ -4,8 +4,6 @@ Flask starter project...
|
|||
|
||||
[![Build Status](https://travis-ci.org/realpython/flask-skeleton.svg?branch=master)](https://travis-ci.org/realpython/flask-skeleton)
|
||||
|
||||
[![Coverage Status](https://coveralls.io/repos/realpython/flask-skeleton/badge.svg?branch=master&service=github)](https://coveralls.io/github/realpython/flask-skeleton?branch=master)
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Basics
|
||||
|
@ -18,13 +16,13 @@ Flask starter project...
|
|||
Update *config.py*, and then run:
|
||||
|
||||
```sh
|
||||
$ export APP_SETTINGS="project.config.DevelopmentConfig"
|
||||
$ export APP_SETTINGS="project.server.config.DevelopmentConfig"
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
$ export APP_SETTINGS="project.config.ProductionConfig"
|
||||
$ export APP_SETTINGS="project.server.config.ProductionConfig"
|
||||
```
|
||||
|
||||
### Create DB
|
||||
|
|
38
manage.py
38
manage.py
|
@ -11,12 +11,16 @@ from flask.ext.migrate import Migrate, MigrateCommand
|
|||
COV = coverage.coverage(
|
||||
branch=True,
|
||||
include='project/*',
|
||||
omit=['*/__init__.py', '*/config/*']
|
||||
omit=[
|
||||
'project/tests/*',
|
||||
'project/server/config.py',
|
||||
'project/server/*/__init__.py'
|
||||
]
|
||||
)
|
||||
COV.start()
|
||||
|
||||
from project import app, db
|
||||
from project.models import User
|
||||
from project.server import app, db
|
||||
from project.server.models import User
|
||||
|
||||
|
||||
migrate = Migrate(app, db)
|
||||
|
@ -29,7 +33,7 @@ manager.add_command('db', MigrateCommand)
|
|||
@manager.command
|
||||
def test():
|
||||
"""Runs the unit tests without coverage."""
|
||||
tests = unittest.TestLoader().discover('tests')
|
||||
tests = unittest.TestLoader().discover('project/tests', pattern='test*.py')
|
||||
result = unittest.TextTestRunner(verbosity=2).run(tests)
|
||||
if result.wasSuccessful():
|
||||
return 0
|
||||
|
@ -40,17 +44,21 @@ def test():
|
|||
@manager.command
|
||||
def cov():
|
||||
"""Runs the unit tests with coverage."""
|
||||
tests = unittest.TestLoader().discover('tests')
|
||||
unittest.TextTestRunner(verbosity=2).run(tests)
|
||||
COV.stop()
|
||||
COV.save()
|
||||
print('Coverage Summary:')
|
||||
COV.report()
|
||||
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||
covdir = os.path.join(basedir, 'tmp/coverage')
|
||||
COV.html_report(directory=covdir)
|
||||
print('HTML version: file://%s/index.html' % covdir)
|
||||
COV.erase()
|
||||
tests = unittest.TestLoader().discover('project/tests')
|
||||
result = unittest.TextTestRunner(verbosity=2).run(tests)
|
||||
if result.wasSuccessful():
|
||||
COV.stop()
|
||||
COV.save()
|
||||
print('Coverage Summary:')
|
||||
COV.report()
|
||||
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||
covdir = os.path.join(basedir, 'tmp/coverage')
|
||||
COV.html_report(directory=covdir)
|
||||
print('HTML version: file://%s/index.html' % covdir)
|
||||
COV.erase()
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
@manager.command
|
||||
|
|
|
@ -1,79 +1 @@
|
|||
# project/__init__.py
|
||||
|
||||
|
||||
#################
|
||||
#### imports ####
|
||||
#################
|
||||
|
||||
import os
|
||||
|
||||
from flask import Flask, render_template
|
||||
from flask.ext.login import LoginManager
|
||||
from flask.ext.bcrypt import Bcrypt
|
||||
from flask.ext.debugtoolbar import DebugToolbarExtension
|
||||
from flask_bootstrap import Bootstrap
|
||||
from flask.ext.sqlalchemy import SQLAlchemy
|
||||
|
||||
|
||||
################
|
||||
#### config ####
|
||||
################
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(os.environ['APP_SETTINGS'])
|
||||
|
||||
|
||||
####################
|
||||
#### extensions ####
|
||||
####################
|
||||
|
||||
login_manager = LoginManager()
|
||||
login_manager.init_app(app)
|
||||
bcrypt = Bcrypt(app)
|
||||
toolbar = DebugToolbarExtension(app)
|
||||
bootstrap = Bootstrap(app)
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
|
||||
###################
|
||||
### blueprints ####
|
||||
###################
|
||||
|
||||
from project.user.views import user_blueprint
|
||||
from project.main.views import main_blueprint
|
||||
app.register_blueprint(user_blueprint)
|
||||
app.register_blueprint(main_blueprint)
|
||||
|
||||
|
||||
###################
|
||||
### flask-login ####
|
||||
###################
|
||||
|
||||
from project.models import User
|
||||
|
||||
login_manager.login_view = "user.login"
|
||||
login_manager.login_message_category = 'danger'
|
||||
|
||||
|
||||
@login_manager.user_loader
|
||||
def load_user(user_id):
|
||||
return User.query.filter(User.id == int(user_id)).first()
|
||||
|
||||
|
||||
########################
|
||||
#### error handlers ####
|
||||
########################
|
||||
|
||||
@app.errorhandler(403)
|
||||
def forbidden_page(error):
|
||||
return render_template("errors/403.html"), 403
|
||||
|
||||
|
||||
@app.errorhandler(404)
|
||||
def page_not_found(error):
|
||||
return render_template("errors/404.html"), 404
|
||||
|
||||
|
||||
@app.errorhandler(500)
|
||||
def server_error_page(error):
|
||||
return render_template("errors/500.html"), 500
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="{{ url_for('main.about') }}">About</a></li>
|
||||
{% if current_user.is_authenticated() %}
|
||||
{% if current_user.is_authenticated %}
|
||||
<li><a href="{{ url_for('user.members') }}">Members</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
{% if current_user.is_authenticated() %}
|
||||
{% if current_user.is_authenticated %}
|
||||
<li><a href="{{ url_for('user.logout') }}">Logout</a></li>
|
||||
{% else %}
|
||||
<li><a href="{{ url_for('user.login') }}"><span class="glyphicon glyphicon-user"></span> Register/Login</a></li>
|
|
@ -1 +0,0 @@
|
|||
# project/public/__init__.py
|
|
@ -0,0 +1,83 @@
|
|||
# project/server/__init__.py
|
||||
|
||||
|
||||
#################
|
||||
#### imports ####
|
||||
#################
|
||||
|
||||
import os
|
||||
|
||||
from flask import Flask, render_template
|
||||
from flask.ext.login import LoginManager
|
||||
from flask.ext.bcrypt import Bcrypt
|
||||
from flask.ext.debugtoolbar import DebugToolbarExtension
|
||||
from flask_bootstrap import Bootstrap
|
||||
from flask.ext.sqlalchemy import SQLAlchemy
|
||||
|
||||
|
||||
################
|
||||
#### config ####
|
||||
################
|
||||
|
||||
app = Flask(
|
||||
__name__,
|
||||
template_folder='../client/templates',
|
||||
static_folder='../client/static'
|
||||
)
|
||||
app.config.from_object(os.environ['APP_SETTINGS'])
|
||||
|
||||
|
||||
####################
|
||||
#### extensions ####
|
||||
####################
|
||||
|
||||
login_manager = LoginManager()
|
||||
login_manager.init_app(app)
|
||||
bcrypt = Bcrypt(app)
|
||||
toolbar = DebugToolbarExtension(app)
|
||||
bootstrap = Bootstrap(app)
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
|
||||
###################
|
||||
### blueprints ####
|
||||
###################
|
||||
|
||||
from project.server.user.views import user_blueprint
|
||||
from project.server.main.views import main_blueprint
|
||||
app.register_blueprint(user_blueprint)
|
||||
app.register_blueprint(main_blueprint)
|
||||
|
||||
|
||||
###################
|
||||
### flask-login ####
|
||||
###################
|
||||
|
||||
from project.server.models import User
|
||||
|
||||
login_manager.login_view = "user.login"
|
||||
login_manager.login_message_category = 'danger'
|
||||
|
||||
|
||||
@login_manager.user_loader
|
||||
def load_user(user_id):
|
||||
return User.query.filter(User.id == int(user_id)).first()
|
||||
|
||||
|
||||
########################
|
||||
#### error handlers ####
|
||||
########################
|
||||
|
||||
@app.errorhandler(403)
|
||||
def forbidden_page(error):
|
||||
return render_template("errors/403.html"), 403
|
||||
|
||||
|
||||
@app.errorhandler(404)
|
||||
def page_not_found(error):
|
||||
return render_template("errors/404.html"), 404
|
||||
|
||||
|
||||
@app.errorhandler(500)
|
||||
def server_error_page(error):
|
||||
return render_template("errors/500.html"), 500
|
|
@ -1,4 +1,4 @@
|
|||
# config.py
|
||||
# project/server/config.py
|
||||
|
||||
import os
|
||||
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||
|
@ -12,12 +12,13 @@ class BaseConfig(object):
|
|||
WTF_CSRF_ENABLED = True
|
||||
DEBUG_TB_ENABLED = False
|
||||
DEBUG_TB_INTERCEPT_REDIRECTS = False
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||
|
||||
|
||||
class DevelopmentConfig(BaseConfig):
|
||||
"""Development configuration."""
|
||||
DEBUG = True
|
||||
BCRYPT_LOG_ROUNDS = 1
|
||||
BCRYPT_LOG_ROUNDS = 4
|
||||
WTF_CSRF_ENABLED = False
|
||||
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'dev.sqlite')
|
||||
DEBUG_TB_ENABLED = True
|
||||
|
@ -27,10 +28,11 @@ class TestingConfig(BaseConfig):
|
|||
"""Testing configuration."""
|
||||
DEBUG = True
|
||||
TESTING = True
|
||||
BCRYPT_LOG_ROUNDS = 1
|
||||
BCRYPT_LOG_ROUNDS = 4
|
||||
WTF_CSRF_ENABLED = False
|
||||
SQLALCHEMY_DATABASE_URI = 'sqlite:///'
|
||||
DEBUG_TB_ENABLED = False
|
||||
PRESERVE_CONTEXT_ON_EXCEPTION = False
|
||||
|
||||
|
||||
class ProductionConfig(BaseConfig):
|
|
@ -0,0 +1 @@
|
|||
# project/server/main/__init__.py
|
|
@ -1,4 +1,4 @@
|
|||
# project/main/views.py
|
||||
# project/server/main/views.py
|
||||
|
||||
|
||||
#################
|
|
@ -1,9 +1,9 @@
|
|||
# project/models.py
|
||||
# project/server/models.py
|
||||
|
||||
|
||||
import datetime
|
||||
|
||||
from project import db, bcrypt
|
||||
from project.server import app, db, bcrypt
|
||||
|
||||
|
||||
class User(db.Model):
|
||||
|
@ -18,7 +18,9 @@ class User(db.Model):
|
|||
|
||||
def __init__(self, email, password, admin=False):
|
||||
self.email = email
|
||||
self.password = bcrypt.generate_password_hash(password)
|
||||
self.password = bcrypt.generate_password_hash(
|
||||
password, app.config.get('BCRYPT_LOG_ROUNDS')
|
||||
)
|
||||
self.registered_on = datetime.datetime.now()
|
||||
self.admin = admin
|
||||
|
|
@ -0,0 +1 @@
|
|||
# project/server/user/__init__.py
|
|
@ -1,4 +1,4 @@
|
|||
# project/user/forms.py
|
||||
# project/server/user/forms.py
|
||||
|
||||
|
||||
from flask_wtf import Form
|
|
@ -1,4 +1,4 @@
|
|||
# project/user/views.py
|
||||
# project/server/user/views.py
|
||||
|
||||
|
||||
#################
|
||||
|
@ -9,9 +9,9 @@ from flask import render_template, Blueprint, url_for, \
|
|||
redirect, flash, request
|
||||
from flask.ext.login import login_user, logout_user, login_required
|
||||
|
||||
from project import bcrypt, db
|
||||
from project.models import User
|
||||
from project.user.forms import LoginForm, RegisterForm
|
||||
from project.server import bcrypt, db
|
||||
from project.server.models import User
|
||||
from project.server.user.forms import LoginForm, RegisterForm
|
||||
|
||||
################
|
||||
#### config ####
|
|
@ -0,0 +1 @@
|
|||
# project/server/tests/__init__.py
|
|
@ -1,16 +1,16 @@
|
|||
# tests/base.py
|
||||
# project/server/tests/base.py
|
||||
|
||||
|
||||
from flask.ext.testing import TestCase
|
||||
|
||||
from project import app, db
|
||||
from project.models import User
|
||||
from project.server import app, db
|
||||
from project.server.models import User
|
||||
|
||||
|
||||
class BaseTestCase(TestCase):
|
||||
|
||||
def create_app(self):
|
||||
app.config.from_object('project.config.TestingConfig')
|
||||
app.config.from_object('project.server.config.TestingConfig')
|
||||
return app
|
||||
|
||||
def setUp(self):
|
|
@ -1,4 +1,4 @@
|
|||
# tests/test_config.py
|
||||
# project/server/tests/test_config.py
|
||||
|
||||
|
||||
import unittest
|
||||
|
@ -6,13 +6,13 @@ import unittest
|
|||
from flask import current_app
|
||||
from flask.ext.testing import TestCase
|
||||
|
||||
from project import app
|
||||
from project.server import app
|
||||
|
||||
|
||||
class TestDevelopmentConfig(TestCase):
|
||||
|
||||
def create_app(self):
|
||||
app.config.from_object('project.config.DevelopmentConfig')
|
||||
app.config.from_object('project.server.config.DevelopmentConfig')
|
||||
return app
|
||||
|
||||
def test_app_is_development(self):
|
||||
|
@ -26,20 +26,20 @@ class TestDevelopmentConfig(TestCase):
|
|||
class TestTestingConfig(TestCase):
|
||||
|
||||
def create_app(self):
|
||||
app.config.from_object('project.config.TestingConfig')
|
||||
app.config.from_object('project.server.config.TestingConfig')
|
||||
return app
|
||||
|
||||
def test_app_is_testing(self):
|
||||
self.assertTrue(current_app.config['TESTING'])
|
||||
self.assertTrue(app.config['DEBUG'] is True)
|
||||
self.assertTrue(app.config['BCRYPT_LOG_ROUNDS'] == 1)
|
||||
self.assertTrue(app.config['BCRYPT_LOG_ROUNDS'] == 4)
|
||||
self.assertTrue(app.config['WTF_CSRF_ENABLED'] is False)
|
||||
|
||||
|
||||
class TestProductionConfig(TestCase):
|
||||
|
||||
def create_app(self):
|
||||
app.config.from_object('project.config.ProductionConfig')
|
||||
app.config.from_object('project.server.config.ProductionConfig')
|
||||
return app
|
||||
|
||||
def test_app_is_production(self):
|
|
@ -1,4 +1,4 @@
|
|||
# tests/test_main.py
|
||||
# project/server/tests/test_main.py
|
||||
|
||||
|
||||
import unittest
|
|
@ -1,4 +1,4 @@
|
|||
# tests/test_user.py
|
||||
# project/server/tests/test_user.py
|
||||
|
||||
|
||||
import datetime
|
||||
|
@ -7,9 +7,9 @@ import unittest
|
|||
from flask.ext.login import current_user
|
||||
|
||||
from base import BaseTestCase
|
||||
from project import bcrypt
|
||||
from project.models import User
|
||||
from project.user.forms import LoginForm
|
||||
from project.server import bcrypt
|
||||
from project.server.models import User
|
||||
from project.server.user.forms import LoginForm
|
||||
|
||||
|
||||
class TestUserBlueprint(BaseTestCase):
|
||||
|
@ -39,7 +39,7 @@ class TestUserBlueprint(BaseTestCase):
|
|||
)
|
||||
response = self.client.get('/logout', follow_redirects=True)
|
||||
self.assertIn(b'You were logged out. Bye!', response.data)
|
||||
self.assertFalse(current_user.is_active())
|
||||
self.assertFalse(current_user.is_active)
|
||||
|
||||
def test_logout_route_requires_login(self):
|
||||
# Ensure logout route requres logged in user.
|
|
@ -1 +0,0 @@
|
|||
# project/user/__init__.py
|
|
@ -1,21 +1,27 @@
|
|||
alembic==0.7.5.post2
|
||||
blinker==1.3
|
||||
coverage==3.7.1
|
||||
alembic==0.8.4
|
||||
bcrypt==2.0.0
|
||||
blinker==1.4
|
||||
cffi==1.4.2
|
||||
coverage==4.0.3
|
||||
dominate==2.1.16
|
||||
Flask==0.10.1
|
||||
Flask-Bcrypt==0.6.2
|
||||
Flask-Bootstrap==3.3.2.1
|
||||
Flask-DebugToolbar==0.9.2
|
||||
Flask-Login==0.2.11
|
||||
Flask-Migrate==1.3.1
|
||||
Flask-Bcrypt==0.7.1
|
||||
Flask-Bootstrap==3.3.5.7
|
||||
Flask-DebugToolbar==0.10.0
|
||||
Flask-Login==0.3.2
|
||||
Flask-Migrate==1.6.0
|
||||
Flask-Script==2.0.5
|
||||
Flask-SQLAlchemy==2.0
|
||||
Flask-SQLAlchemy==2.1
|
||||
Flask-Testing==0.4.2
|
||||
Flask-WTF==0.11
|
||||
Flask-WTF==0.12
|
||||
itsdangerous==0.24
|
||||
Jinja2==2.7.3
|
||||
Mako==1.0.1
|
||||
Jinja2==2.8
|
||||
Mako==1.0.3
|
||||
MarkupSafe==0.23
|
||||
python-bcrypt==0.3.1
|
||||
SQLAlchemy==0.9.9
|
||||
Werkzeug==0.10.4
|
||||
WTForms==2.0.2
|
||||
pycparser==2.14
|
||||
python-editor==0.5
|
||||
six==1.10.0
|
||||
SQLAlchemy==1.0.11
|
||||
visitor==0.1.2
|
||||
Werkzeug==0.11.3
|
||||
WTForms==2.1
|
||||
|
|
Loading…
Reference in New Issue