31 | This is table is rendered on the Client. JavaScript code requests the data from /api/users and writes it to this page. 32 |
33 || Id | Username | 39 |
|---|
├── e2e ├── config.json └── test.js ├── .python-version ├── App ├── models │ ├── __init__.py │ └── user.py ├── tests │ ├── __init__.py │ └── test_app.py ├── static │ ├── style.css │ ├── main.js │ └── static-user.html ├── default_config.py ├── controllers │ ├── __init__.py │ ├── initialize.py │ ├── user.py │ └── auth.py ├── __init__.py ├── templates │ ├── admin │ │ └── index.html │ ├── message.html │ ├── index.html │ ├── 401.html │ ├── users.html │ └── layout.html ├── database.py ├── views │ ├── __init__.py │ ├── index.py │ ├── admin.py │ ├── user.py │ └── auth.py ├── config.py └── main.py ├── .flaskenv ├── images ├── fig1.png └── gitperms.png ├── setup.cfg ├── .vscode └── settings.json ├── pytest.ini ├── requirements.txt ├── gunicorn_config.py ├── .Dockerfile ├── package.json ├── .github └── workflows │ └── dev.yml ├── render.yaml ├── .devcontainer ├── Dockerfile └── devcontainer.json ├── wsgi.py ├── .gitignore └── readme.md /e2e/config.json: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.python-version: -------------------------------------------------------------------------------- 1 | 3.9.10 2 | -------------------------------------------------------------------------------- /App/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .user import * -------------------------------------------------------------------------------- /App/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from .test_app import * -------------------------------------------------------------------------------- /App/static/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | padding: 0; 3 | } -------------------------------------------------------------------------------- /.flaskenv: -------------------------------------------------------------------------------- 1 | FLASK_RUN_PORT=8080 2 | FLASK_APP=wsgi.py 3 | FLASK_DEBUG=True -------------------------------------------------------------------------------- /images/fig1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uwidcit/flaskmvc/HEAD/images/fig1.png -------------------------------------------------------------------------------- /images/gitperms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uwidcit/flaskmvc/HEAD/images/gitperms.png -------------------------------------------------------------------------------- /App/default_config.py: -------------------------------------------------------------------------------- 1 | SQLALCHEMY_DATABASE_URI="sqlite:///temp-database.db" 2 | SECRET_KEY="secret key" -------------------------------------------------------------------------------- /App/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | from .user import * 2 | from .auth import * 3 | from .initialize import * 4 | -------------------------------------------------------------------------------- /App/__init__.py: -------------------------------------------------------------------------------- 1 | from .models import * 2 | from .views import * 3 | from .controllers import * 4 | from .main import * -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [tool:pytest] 2 | testpaths = App/tests 3 | 4 | [coverage:run] 5 | branch = True 6 | source = 7 | App -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.testing.unittestEnabled": false, 3 | "python.testing.pytestEnabled": true 4 | } -------------------------------------------------------------------------------- /App/templates/admin/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'admin/master.html' %} 2 | 3 | {% block body %} 4 |
Hello world
5 | {% endblock %} -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | filterwarnings = ignore::DeprecationWarning 3 | testpaths = App/tests 4 | log_cli = 1 5 | log_cli_level = INFO 6 | log_cli_format = %(message)s 7 | log_cli_date_format=%Y-%m-%d %H:%M:%S -------------------------------------------------------------------------------- /App/controllers/initialize.py: -------------------------------------------------------------------------------- 1 | from .user import create_user 2 | from App.database import db 3 | 4 | 5 | def initialize(): 6 | db.drop_all() 7 | db.create_all() 8 | create_user('bob', 'bobpass') 9 | -------------------------------------------------------------------------------- /App/database.py: -------------------------------------------------------------------------------- 1 | from flask_sqlalchemy import SQLAlchemy 2 | from flask_migrate import Migrate 3 | 4 | 5 | db = SQLAlchemy() 6 | 7 | def get_migrate(app): 8 | return Migrate(app, db) 9 | 10 | def create_db(): 11 | db.create_all() 12 | 13 | def init_db(app): 14 | db.init_app(app) -------------------------------------------------------------------------------- /App/views/__init__.py: -------------------------------------------------------------------------------- 1 | # blue prints are imported 2 | # explicitly instead of using * 3 | from .user import user_views 4 | from .index import index_views 5 | from .auth import auth_views 6 | from .admin import setup_admin 7 | 8 | 9 | views = [user_views, index_views, auth_views] 10 | # blueprints must be added to this list -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==2.3.3 2 | Flask-SQLAlchemy==3.1.1 3 | Flask-Migrate==3.1.0 4 | Flask-Reuploaded==1.2.0 5 | Flask-Cors==3.0.10 6 | Flask-JWT-Extended==4.4.4 7 | Flask-Admin==1.6.1 8 | Werkzeug>=3.0.0 9 | click==8.1.3 10 | gunicorn==20.1.0 11 | gevent==22.10.2 12 | pytest==7.0.1 13 | psycopg2-binary==2.9.9 14 | python-dotenv==1.0.1 15 | rich==13.4.2 16 | 17 | -------------------------------------------------------------------------------- /App/templates/message.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block title %}{{title}}{% endblock %} 3 | {% block page %}{{title}}{% endblock %} 4 | 5 | {{ super() }} 6 | 7 | {% block content %} 8 |{{message}}
12 |Welcome {{current_user.username}}
11 | {% endif %} 12 |This is a boileplate flask application which follows the MVC pattern for structuring the project.
13 | {% endblock %} -------------------------------------------------------------------------------- /gunicorn_config.py: -------------------------------------------------------------------------------- 1 | # gunicorn_config.py 2 | import multiprocessing 3 | 4 | # The socket to bind. 5 | # "0.0.0.0" to bind to all interfaces. 8000 is the port number. 6 | bind = "0.0.0.0:8080" 7 | 8 | # The number of worker processes for handling requests. 9 | workers = 4 10 | 11 | # Use the 'gevent' worker type for async performance. 12 | worker_class = 'gevent' 13 | 14 | # Log level 15 | loglevel = 'info' 16 | 17 | # Where to log to 18 | accesslog = '-' # '-' means log to stdout 19 | errorlog = '-' # '-' means log to stderr -------------------------------------------------------------------------------- /App/static/main.js: -------------------------------------------------------------------------------- 1 | 2 | async function getUserData(){ 3 | const response = await fetch('/api/users'); 4 | return response.json(); 5 | } 6 | 7 | function loadTable(users){ 8 | const table = document.querySelector('#result'); 9 | for(let user of users){ 10 | table.innerHTML += `10 | This is table is renderd on the Server. Flask gets the data from the database and uses jinja templates to dyanmically render this page when a request is sent to /users. 11 |
12 || Id | Username | 42 |
|---|---|
| {{user.id}} | 48 |{{user.username}} | 49 |
31 | This is table is rendered on the Client. JavaScript code requests the data from /api/users and writes it to this page. 32 |
33 || Id | Username | 39 |
|---|