-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 1bb5297
Showing
29 changed files
with
1,012 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
**/venv | ||
**/__pycache__ | ||
**/.pytest_cache | ||
**/*.sqlite |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
# Flask Project Scaffold | ||
|
||
![book](book.jpg) | ||
|
||
## [Flask Web Development, 2nd - O'Reilly 2018](https://www.amazon.com/Flask-Web-Development-Developing-Applications/dp/1491991739/) | ||
|
||
Chapter 7 Large Application Structure | ||
|
||
## Usage | ||
|
||
- Clone this git repo | ||
- Copy `proj` dir to your proj dir, and rename properly | ||
- Create `venv` and activate it | ||
- `python -m venv venv --prompt flask` | ||
- `venv\Scripts\activate` | ||
- `python -m pip install pip --upgrade` | ||
- Install packages `pip install -r requirements.txt` | ||
- set env `FLASK_APP="flask_app"`, `FLASK_ENV="development"` | ||
- Run `flask run` | ||
|
||
### Project Structure | ||
|
||
```text | ||
|-app/ | ||
|-templates/ | ||
|-static/ | ||
|-main/ | ||
|-__init__.py | ||
|-errors.py | ||
|-forms.py | ||
|-views.py | ||
|-__init__.py | ||
|-models.py | ||
|-email.py | ||
|-migrations/ | ||
|-tests/ | ||
|-__init__.py | ||
|-test*.py | ||
|-venv/ | ||
|-requirements.txt | ||
|-config.py | ||
|-flask_appy.py | ||
``` | ||
|
||
`flask_scaffold.py` create this folder structure | ||
|
||
### Application Factory | ||
|
||
```python | ||
### file: 'app/__init__.py' | ||
|
||
from flask import Flask, render_template | ||
from flask_bootstrap import Bootstrap5 as Bootstrap | ||
|
||
from flask_moment import Moment | ||
from flask_sqlalchemy import SQLAlchemy | ||
|
||
from flask_mail import Mail | ||
|
||
from config import config | ||
|
||
bootstrap = Bootstrap() | ||
moment = Moment() | ||
db = SQLAlchemy() | ||
|
||
mail = Mail() | ||
|
||
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) | ||
moment.init_app(app) | ||
db.init_app(app) | ||
|
||
mail.init_app(app) | ||
|
||
# Register 'main' blueprint | ||
from .main import main as main_bp | ||
app.register_blueprint(main_bp) | ||
|
||
return app | ||
``` | ||
|
||
### Blueprint | ||
|
||
```python | ||
### file 'app/main/__init__.py' | ||
|
||
from flask import Blueprint | ||
main = Blueprint('main', __name__) | ||
|
||
from . import views, errors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
""" | ||
Create Flask application directory structure | ||
- Base on "Flask Web Development, 2nd - O'Reilly 2018" "Chapter 7" | ||
- Be aware: the files are dummy file, empty, wihout content | ||
Usage | ||
----------------- | ||
python flask_scaffold.py <proj_home> | ||
Argument | ||
----------------- | ||
sys.argv[1]: String | ||
project home dir | ||
- can be absolute path, i.e: "D:\temp\proj" | ||
- or relative path, "proj", or ".\proj" | ||
Errors | ||
------------------ | ||
if 2nd argument(sys.argv[1]) is not set: | ||
exit -1 | ||
""" | ||
|
||
import os, sys | ||
|
||
""" | ||
Directories to create | ||
- ["app", "templates"] means to create "app/templates" dir | ||
""" | ||
DIRS = [ | ||
["app", "templates"], # "app/templates" dir | ||
["app", "static"], | ||
["app", "main"], | ||
["migrations"], | ||
["tests"], | ||
["venv"], | ||
] | ||
|
||
""" | ||
Files to create | ||
- ["app", "main", "__init__.py"] means to create "app/main/__init__.py" file | ||
""" | ||
FILES = [ | ||
["app", "main", "__init__.py"], # "app/main/__init__.py" file | ||
["app", "main", "errors.py"], | ||
["app", "main", "forms.py"], | ||
["app", "main", "views.py"], | ||
["app", "__init__.py"], | ||
["app", "models.py"], | ||
["app", "email.py"], | ||
["tests", "__init__.py"], | ||
["requirements.txt"], | ||
["config.py"], | ||
["flask_app.py"] | ||
] | ||
|
||
def get_proj_home(home): | ||
if os.path.isabs(home): | ||
return home | ||
else: | ||
phome = os.path.abspath(os.path.dirname(__file__)) | ||
phome = os.path.join(phome, home) | ||
return phome | ||
|
||
def create_dirs_files(home): | ||
from pathlib import Path | ||
for fd in DIRS + FILES: | ||
target =os.path.join(home, *fd) | ||
print("Create: " + target) | ||
|
||
# Skip if target exists | ||
if os.path.exists(target): | ||
continue | ||
|
||
# for DIRS | ||
if fd in DIRS: | ||
os.makedirs(target) | ||
|
||
# for FILES | ||
if fd in FILES: | ||
Path(target).touch() | ||
|
||
if __name__ == '__main__': | ||
|
||
# Check command line argument, 2nd argument is Proj HOME | ||
if len(sys.argv) < 2: | ||
msg = "Error!\n" + \ | ||
"Please specify proj home as:\n" + \ | ||
f" python {__file__} abc \n" | ||
print(msg) | ||
exit(-1) | ||
|
||
# Get project home | ||
home = get_proj_home(sys.argv[1]) | ||
print("Project home: " + home) | ||
|
||
# create dirs and files | ||
create_dirs_files(home) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
**/venv | ||
**/__pycache__ | ||
**/.pytest_cache | ||
**/*.sqlite |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
from flask import Flask, render_template | ||
from flask_bootstrap import Bootstrap5 as Bootstrap | ||
|
||
from flask_moment import Moment | ||
from flask_sqlalchemy import SQLAlchemy | ||
|
||
from flask_mail import Mail | ||
|
||
from config import config | ||
|
||
bootstrap = Bootstrap() | ||
moment = Moment() | ||
db = SQLAlchemy() | ||
|
||
mail = Mail() | ||
|
||
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) | ||
moment.init_app(app) | ||
db.init_app(app) | ||
|
||
mail.init_app(app) | ||
|
||
from .main import main as main_bp | ||
app.register_blueprint(main_bp) | ||
|
||
return app |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from flask import Blueprint | ||
|
||
main = Blueprint('main', __name__) | ||
|
||
from . import views, errors | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from flask_wtf import FlaskForm | ||
from wtforms import StringField, SubmitField | ||
from wtforms.validators import DataRequired | ||
|
||
class NameForm(FlaskForm): | ||
name = StringField('Your name:', validators=[DataRequired()]) | ||
submit = SubmitField('Submit') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from datetime import datetime | ||
|
||
from flask import render_template, session, redirect, url_for | ||
|
||
from . import main | ||
from .forms import NameForm | ||
from .. import db | ||
from ..models import User | ||
|
||
@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 | ||
else: | ||
session['known'] = True | ||
return redirect(url_for('.index')) | ||
|
||
return render_template('index.html', | ||
title="Home", | ||
form=form, | ||
name=session.get('name'), | ||
known=session.get('known', False)) # |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{% extends "base.html" %} | ||
|
||
{% block title %} | ||
Page not found (404) | ||
{% endblock %} | ||
|
||
{% block page_content %} | ||
<div class="page-header"> | ||
<h1>Sorry, Page not found (404)</h1> | ||
</div> | ||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{% extends "base.html" %} | ||
|
||
{% block title %} | ||
Page not found (404) | ||
{% endblock %} | ||
|
||
{% block page_content %} | ||
<div class="page-header"> | ||
<h1>Sorry, Internal Error (500)</h1> | ||
</div> | ||
{% endblock %} | ||
|
Oops, something went wrong.