refctored project struture, upgraded project dependencoes

main
Michael Herman 2015-12-25 14:00:00 +01:00
parent f16cd5eff6
commit d1d41606cd
35 changed files with 168 additions and 145 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.env
env
venv
temp

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>&nbsp;Register/Login</a></li>

View File

@ -1 +0,0 @@
# project/public/__init__.py

View File

@ -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

View File

@ -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):

View File

@ -0,0 +1 @@
# project/server/main/__init__.py

View File

@ -1,4 +1,4 @@
# project/main/views.py
# project/server/main/views.py
#################

View File

@ -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

View File

@ -0,0 +1 @@
# project/server/user/__init__.py

View File

@ -1,4 +1,4 @@
# project/user/forms.py
# project/server/user/forms.py
from flask_wtf import Form

View File

@ -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 ####

View File

@ -0,0 +1 @@
# project/server/tests/__init__.py

View File

@ -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):

View File

@ -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):

View File

@ -1,4 +1,4 @@
# tests/test_main.py
# project/server/tests/test_main.py
import unittest

View File

@ -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.

View File

@ -1 +0,0 @@
# project/user/__init__.py

View File

@ -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

View File