Script to create a flask project skeleton in my desired format. Configs from file, basic SQLAlchemy with default sqlite3 db, Makefile, app blueprint separation, etc.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

272 lines
7.5 KiB

# Create the blueprint for a new flask project
if [[ -z $1 ]]; then
echo "[FlaskCreate] Syntax Error: flask-create.sh <project_name> <parent_directory:default cwd>"
exit;
fi
PROJECT_NAME=$1
PROJECT_ROOT=$2
if [[ -z $PROJECT_ROOT ]]; then
PROJECT_ROOT=$(pwd)
fi
echo "-=[FlaskCreate]=-";
echo "Project Name: $PROJECT_NAME";
echo "Project Root: $PROJECT_ROOT/$PROJECT_NAME";
echo "Start a new Flask project? (y/n)";
read START_CONFIRM;
if [[ $START_CONFIRM != y && $START_CONFIRM != Y ]]; then
exit;
fi
PROJECT_FOLDER=$PROJECT_ROOT/$PROJECT_NAME
echo "";
echo "[FlaskCreate] Creating directory $PROJECT_FOLDER...";
mkdir $PROJECT_FOLDER;
mkdir $PROJECT_FOLDER/data;
mkdir $PROJECT_FOLDER/$PROJECT_NAME;
touch $PROJECT_FOLDER/uwsgi.ini;
echo "[FlaskCreate] Generating uwsgi config...";
echo "[uwsgi]
module = wsgi:application
master = true
processes = 4
socket = $PROJECT_NAME.sock
chmod-scoket = 660
vacuum = true
die-on-term = true
" > $PROJECT_FOLDER/uwsgi.ini;
touch $PROJECT_FOLDER/start.py;
echo "from $PROJECT_NAME import create_app
app = create_app()
if __name__ == \"__main__\":
app.run()
" > $PROJECT_FOLDER/start.py;
echo "[FlaskCreate] Creating Flask app module files...";
touch $PROJECT_FOLDER/$PROJECT_NAME/__init__.py;
echo "from flask import Flask
def create_app():
app = Flask(__name__)
app.config.from_object('$PROJECT_NAME.default_settings')
app.config.from_envvar('FLASK_SETTINGS_FILE')
# Prep the database
from $PROJECT_NAME.models import db
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///../data/$PROJECT_NAME.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
# Load our views
from $PROJECT_NAME.views import default_views
app.register_blueprint(default_views)
# from $PROJECT_NAME.<app_name>.views import app_views
# app.register_blueprint(app_views)
# Load our CLI commands
from $PROJECT_NAME.commands import default_cli
app.cli.add_command(default_cli)
# from $PROJECT_NAME.<app_name>.commands import app_cli
# app.cli.add_command(app_cli)
return app
" > $PROJECT_FOLDER/$PROJECT_NAME/__init__.py;
echo "[FlaskCreate] Generating SQLAlchemy base model...";
touch $PROJECT_FOLDER/$PROJECT_NAME/models.py;
echo "from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class BaseModel(db.Model):
__abstract__ = True
id = db.Column(db.Integer, primary_key=True)
created_at = db.Column(db.DateTime)
" > $PROJECT_FOLDER/$PROJECT_NAME/models.py;
echo "[FlaskCreate] Generating basic CLI commands...";
touch $PROJECT_FOLDER/$PROJECT_NAME/commands.py;
echo "import click
from flask.cli import AppGroup
from $PROJECT_NAME.models import db
default_cli = AppGroup('$PROJECT_NAME')
@default_cli.command('initdb')
def initialize_database():
from $PROJECT_NAME import models
# from $PROJECT_NAME.<app_name> import models
db.create_all()
" > $PROJECT_FOLDER/$PROJECT_NAME/commands.py;
echo "[FlaskCreate] Generating default views...";
touch $PROJECT_FOLDER/$PROJECT_NAME/views.py;
echo "from flask import current_app, Blueprint, render_template
default_views = Blueprint('default_views', __name__, url_prefix='/')
@default_views.route('/')
def index():
return render_template('index.html')
" > $PROJECT_FOLDER/$PROJECT_NAME/views.py;
echo "[FlaskCreate] Initializing default templates...";
TEMPLATE_DIR=$PROJECT_FOLDER/$PROJECT_NAME/templates
mkdir $TEMPLATE_DIR;
touch $TEMPLATE_DIR/base.html;
touch $TEMPLATE_DIR/index.html;
echo " <!doctype html>
<html>
<head>
<title>{% block title %}{% endblock %} - $PROJECT_NAME</title>
<meta charset=\"utf-8\">
<meta name=\"viewport\" contents=\"width=device-width, initial-scale=1\">
<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/uikit/3.2.0/css/uikit.min.css\" integrity=\"sha256-5YtK9j+Nl/245lAkSjrIs600d6edKTevi+3JYdjuHhY=\" crossorigin=\"anonymous\" />
<script src=\"https://cdnjs.cloudflare.com/ajax/libs/uikit/3.2.0/js/uikit.min.js\" integrity=\"sha256-rhLALrRmAQVu/OxzVDpQaiHAEMxiRSN8h8RDydUEh2g=\" crossorigin=\"anonymous\"></script>
{% block head %} {% endblock %}
</head>
<body>
<nav class=\"uk-navbar-container\" uk-navbar>
<div class=\"uk-navbar-left\">
<a href=\"\" class=\"uk-navbar-item uk-logo\">$PROJECT_NAME</a>
</div>
<div class=\"uk-navbar-center\">
<ul class=\"uk-navbar-nav\">
<li class=\"uk-active\"><a href=\"\">Nav Item 1</a></li>
<li><a href=\"\">Nav Item 2</a></li>
<li><a href=\"\">Nav Item 3</a></li>
<li><a href=\"\">Nav Item 4</a></li>
</ul>
</div>
</nav>
<div class=\"uk-container\">
{% block content %}{% endblock %}
</div>
</body>
</html>
" > $TEMPLATE_DIR/base.html;
echo "{% extends \"base.html\" %}
{% block title %}$PROJECT_NAME Home{% endblock %}
{% block content %}
<div>
</div>
{% endblock %}
{% block head %}
<style>
</style>
{% endblock %}
" > $TEMPLATE_DIR/index.html;
echo "[FlaskCreate] Creating default_settings config file...";
touch $PROJECT_FOLDER/$PROJECT_NAME/default_settings.py;
echo "# Default Configuration
SECRET_KEY = 'asecretkeyshouldchange'
# Flask-SQLAlchemy
SQLALCHEMY_TRACK_MODIFICATIONS = False
" > $PROJECT_FOLDER/$PROJECT_NAME/default_settings.py;
echo "[FlaskCreate] Creating environment config files...";
mkdir $PROJECT_FOLDER/config;
touch $PROJECT_FOLDER/config/prod.cfg; touch $PROJECT_FOLDER/config/dev.cfg
PROD_KEY=$(echo $(od -vN 20 -An -tx1 /dev/urandom | tr -d " \n"))
DEV_KEY=$(echo $(od -vN 20 -An -tx1 /dev/urandom | tr -d " \n"))
echo "# Default Configuration
DEBUG = True
SECRET_KEY = \"$DEV_KEY\"
# Flask-SQLAlchemy
SQLALCHEMY_DATABASE_URI = 'sqlite:///../data/acks.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
" > $PROJECT_FOLDER/config/dev.cfg
echo "# Default Configuration
DEBUG = False
SECRET_KEY = \"$PROD_KEY\"
# Flask-SQLAlchemy
SQLALCHEMY_DATABASE_URI = 'sqlite:///../data/acks.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
" > $PROJECT_FOLDER/config/prod.cfg
echo "[FlaskCreate] Generating a Makefile...";
touch $PROJECT_FOLDER/Makefile;
echo -e ".PHONY: run debug clean
bin/activate: requirements.txt
\t test -f bin/activate || $(which python3) -m venv .
\t bin/pip install -Ur requirements.txt
\t touch bin/activate
run: bin/activate
\t . bin/activate; FLASK_SETTINGS_FILE=../config/prod.cfg FLASK_ENV=production FLASK_APP=start.py flask run --host=0.0.0.0
debug: bin/activate
\t . bin/activate; FLASK_SETTINGS_FILE=../config/dev.cfg FLASK_ENV=development FLASK_APP=start.py flask run --host=0.0.0.0
clean:
\t rm -rf bin/ include/ lib/ lib64/ __pycache__/ share/; rm pyvenv.cfg
" > $PROJECT_FOLDER/Makefile
echo "[FlaskCreate] Initializing a git repository and creating initial commit...";
cd $PROJECT_FOLDER;
touch $PROJECT_FOLDER/.gitignore
echo "# Python
*.py[co]
# Vim
*.swp
# Virtualenv
bin
include
lib
lib64
__pycache__
share
pyvenv.cfg
# App specific
data
config
" > $PROJECT_FOLDER/.gitignore
git init $PROJECT_FOLDER &> /dev/null;
git add . &> /dev/null;
git commit -m "Initial commit (FlaskCreate)" &> /dev/null;
echo "[FlaskCreate] Creating Python3 virtual environment...";
python3 -m venv $PROJECT_FOLDER
source $PROJECT_FOLDER/bin/activate
echo "[FlaskCreate] Installing dependencies...";
pip install flask flask-sqlalchemy &> /dev/null
pip freeze > $PROJECT_FOLDER/requirements.txt;
echo "[FlaskCreate] Finished. Project lives at $PROJECT_FOLDER."
cd $PROJECT_FOLDER;