Skip to content

Commit b816de2

Browse files
committed
Migrate to Gunicorn; Resolve prompt bug; Update User model; Style updates.
1 parent 631137b commit b816de2

File tree

16 files changed

+69
-834
lines changed

16 files changed

+69
-834
lines changed

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ LOCAL_PYTHON := $(VIRTUAL_ENV)/bin/python3
55
define HELP
66
Manage $(PROJECT_NAME). Usage:
77

8-
make run - Run $(PROJECT_NAME) locally.
8+
make run - Run $(PROJECT_NAME) locally (not suitable to serve `production` applications).
99
make install - Create local virtualenv & install dependencies.
10-
make deploy - Set up project & run locally.
10+
make deploy - Set up project & run locally (not suitable to serve `production` applications).
1111
make update - Update dependencies via Poetry and output resulting `requirements.txt`.
1212
make format - Run Python code formatter & sort dependencies.
1313
make lint - Check code formatting with flake8.
@@ -33,7 +33,7 @@ $(VIRTUAL_ENV):
3333
.PHONY: run
3434
run: env
3535
export LESS_BIN=$(shell which lessc) && \
36-
$(LOCAL_PYTHON) -m main
36+
$(LOCAL_PYTHON) -m gunicorn -w 4 wsgi:app
3737

3838
.PHONY: install
3939
install: env

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
![Flask](https://img.shields.io/badge/Flask-v^2.3.3-blue.svg?longCache=true&logo=flask&style=flat-square&logoColor=white&colorB=5e81ac&colorA=4c566a)
55
![Flask-Login](https://img.shields.io/badge/Flask--Login-v0.6.2-blue.svg?longCache=true&logo=flask&style=flat-square&logoColor=white&colorB=5e81ac&colorA=4c566a)
66
![Flask-Session](https://img.shields.io/badge/Flask--Session-v0.5.0-blue.svg?longCache=true&logo=flask&style=flat-square&logoColor=white&colorB=5e81ac&colorA=4c566a)
7+
![Flask-SQLAlchemy](https://img.shields.io/badge/Flask--SQLAlchemy-v3.0.5-red.svg?longCache=true&style=flat-square&logo=scala&logoColor=white&colorA=4c566a&colorB=bf616a)
78
![Redis](https://img.shields.io/badge/Redis-v5.0.0-red.svg?longCache=true&style=flat-square&logo=redis&logoColor=white&colorA=4c566a&colorB=bf616a)
89
![GitHub Last Commit](https://img.shields.io/github/last-commit/google/skia.svg?style=flat-square&colorA=4c566a&colorB=a3be8c&logo=GitHub)
910
[![GitHub Issues](https://img.shields.io/github/issues/hackersandslackers/flask-session-tutorial.svg?style=flat-square&colorA=4c566a&logo=GitHub&colorB=ebcb8b)](https://github.com/hackersandslackers/flask-session-tutorial/issues)

config.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import redis
55
from dotenv import load_dotenv
66

7-
basedir = path.abspath(path.dirname(__file__))
8-
load_dotenv(path.join(basedir, ".env"))
7+
BASE_DIR = path.abspath(path.dirname(__file__))
8+
load_dotenv(path.join(BASE_DIR, ".env"))
99

1010

1111
class Config:
@@ -24,15 +24,15 @@ class Config:
2424
SESSION_TYPE = "redis"
2525
SESSION_REDIS = redis.from_url(REDIS_URI)
2626

27-
# Flask-Assets
27+
# Flask-SQLAlchemy
28+
SQLALCHEMY_DATABASE_URI = environ.get("SQLALCHEMY_DATABASE_URI")
29+
SQLALCHEMY_TRACK_MODIFICATIONS = False
30+
SQLALCHEMY_ECHO = False
31+
32+
# Flask-Assets (Optional)
2833
LESS_BIN = system("which lessc")
2934
ASSETS_DEBUG = False
3035
LESS_RUN_IN_DEBUG = False
3136
STATIC_FOLDER = "static"
3237
TEMPLATES_FOLDER = "templates"
3338
COMPRESSOR_DEBUG = environ.get("COMPRESSOR_DEBUG")
34-
35-
# Flask-SQLAlchemy
36-
SQLALCHEMY_DATABASE_URI = environ.get("SQLALCHEMY_DATABASE_URI")
37-
SQLALCHEMY_TRACK_MODIFICATIONS = environ.get("SQLALCHEMY_TRACK_MODIFICATIONS")
38-
SQLALCHEMY_ECHO = environ.get("SQLALCHEMY_ECHO")

flask_session_tutorial/assets.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,21 @@
33
from flask_assets import Bundle, Environment
44

55

6+
def compile_static_assets(app: Flask):
7+
"""
8+
Compile all asset bundles.
9+
10+
:param Flask app: Top-level Flask application.
11+
"""
12+
compile_stylesheets(app)
13+
compile_javascript(app)
14+
15+
616
def compile_stylesheets(app: Flask):
717
"""
8-
Generate stylesheets for thr application.
18+
Generate CSS from .LESS source.
919
10-
:param Flask app: Parent application to generate styles for.
20+
:param Flask app: Top-level Flask application.
1121
"""
1222
assets = Environment(app)
1323
Environment.auto_build = True
@@ -36,9 +46,9 @@ def compile_stylesheets(app: Flask):
3646

3747
def compile_javascript(app: Flask):
3848
"""
39-
Generate static assets for main views.
49+
Bundle and minimize Javascript source files.
4050
41-
:param Flask app: Parent Flask application to generate Javascript bundles for.
51+
:param Flask app: Top-level Flask application.
4252
"""
4353
assets = Environment(app)
4454
Environment.auto_build = True
@@ -51,14 +61,4 @@ def compile_javascript(app: Flask):
5161
assets.register("js_all", js_bundle)
5262
# Build assets in development mode
5363
if app.config.get("ENVIRONMENT") != "production":
54-
js_bundle.build(force=True)
55-
56-
57-
def compile_static_assets(app: Flask):
58-
"""
59-
Compile all asset bundles.
60-
61-
:param Flask app: Parent Flask application to generate asset bundles for.
62-
"""
63-
compile_stylesheets(app)
64-
compile_javascript(app)
64+
js_bundle.build(force=True)

flask_session_tutorial/auth.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,22 @@
2020
@auth_blueprint.route("/signup", methods=["GET", "POST"])
2121
def signup() -> Response:
2222
"""
23-
Sign-up form to create new user accounts.
23+
View for new users to sign up with new accounts.
2424
2525
GET: Serve sign-up page.
2626
POST: Validate form, create account, redirect user to dashboard.
27+
28+
:response: Response
2729
"""
2830
form = SignupForm()
2931
if form.validate_on_submit():
30-
existing_user = User.query.filter_by(email=form.email.data).first()
32+
existing_user = User.query.filter_by(email=form.user_email.data).first()
3133
if existing_user is None:
32-
user = User(name=form.name.data, email=form.email.data, website=form.website.data)
33-
user.set_password(form.password.data)
34+
user = User(name=form.name.data, email=form.user_email.data, website=form.website.data)
35+
user.set_password(form.user_password.data)
3436
db.session.add(user)
3537
db.session.commit() # Create new user
3638
login_user(user) # Log in as newly created user
37-
print(user)
3839
return redirect(url_for("main.dashboard"))
3940
flash("A user already exists with that email address.")
4041
return render_template(
@@ -46,20 +47,22 @@ def signup() -> Response:
4647
)
4748

4849

49-
@auth_blueprint.route("/login", methods=["GET", "POST"])
50+
@auth_blueprint.route("/", methods=["GET", "POST"])
5051
def login() -> Response:
5152
"""
5253
Log-in page for registered users.
5354
5455
GET: Serve Log-in page.
5556
POST: Validate form and redirect user to dashboard.
57+
58+
:returns: Response
5659
"""
5760
if current_user.is_authenticated:
5861
return redirect(url_for("main.dashboard")) # Bypass if user is logged in
5962
form = LoginForm()
6063
if form.validate_on_submit():
61-
user = User.query.filter_by(email=form.email.data).first() # Validate Login Attempt
62-
if user and user.check_password(password=form.password.data):
64+
user = User.query.filter_by(email=form.user_email.data).first() # Validate Login Attempt
65+
if user and user.check_password(password=form.user_password.data):
6366
login_user(user)
6467
next_page = request.args.get("next")
6568
return redirect(next_page or url_for("main.dashboard"))
@@ -68,7 +71,7 @@ def login() -> Response:
6871
return render_template(
6972
"login.jinja2",
7073
form=form,
71-
title="Log in.",
74+
title="Log In",
7275
template="login-page",
7376
body="Log in with your User account.",
7477
)

flask_session_tutorial/models.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,18 @@
66

77

88
class User(UserMixin, db.Model):
9-
"""Model for user accounts."""
9+
"""User account database model."""
1010

1111
__tablename__ = "flasksession-users"
1212

1313
id = db.Column(db.Integer, primary_key=True)
14-
name = db.Column(db.String(200), nullable=False, unique=False)
15-
email = db.Column(db.String(40), unique=True, nullable=False)
16-
password = db.Column(db.String(200), primary_key=False, unique=False, nullable=False)
17-
website = db.Column(db.String(60), index=False, unique=False, nullable=True)
18-
created_on = db.Column(db.DateTime, index=False, unique=False, nullable=True)
19-
last_login = db.Column(db.DateTime, index=False, unique=False, nullable=True)
14+
name = db.Column(db.String(255), nullable=False, unique=False)
15+
email = db.Column(db.String(255), unique=True, nullable=False)
16+
password = db.Column(db.String(255), nullable=False)
17+
website = db.Column(db.String(255), nullable=True)
18+
last_login = db.Column(db.DateTime)
19+
created_at = db.Column(db.DateTime, server_default=db.func.now())
20+
updated_at = db.Column(db.DateTime, server_default=db.func.now(), server_onupdate=db.func.now())
2021

2122
def set_password(self, password):
2223
"""Create hashed password."""

flask_session_tutorial/routes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
)
1212

1313

14-
@main_blueprint.route("/", methods=["GET"])
14+
@main_blueprint.route("/dashboard", methods=["GET"])
1515
@login_required
1616
def dashboard() -> Response:
1717
"""

flask_session_tutorial/static/dist/css/account.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flask_session_tutorial/static/src/less/account.less

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,19 @@
2323
margin: 0 auto 20px;
2424

2525
img {
26-
width: 30px;
26+
width: 40px;
2727
margin: auto;
2828

2929
@media (max-width: 600px) {
30-
width: 25px;
30+
width: 30px;
3131
}
3232
}
3333
}
3434

3535
.alert-warning {
36-
color: #856404;
37-
background-color: #fff3cd;
38-
border-color: #ffeeba;
36+
color: @alert-font-color;
37+
background-color: @alert-background-color;
38+
border-color: @alert-border-color;
3939
font-weight: 300;
4040
font-size: .8em;
4141
margin: 30px 0;
@@ -47,7 +47,7 @@
4747
}
4848

4949
.close {
50-
color: #856404;
50+
color: @alert-font-color;
5151
font-weight: 300;
5252
order: 1;
5353
outline: none !important;
@@ -64,7 +64,8 @@
6464
font-family: @body-font;
6565

6666
button.close {
67-
padding: 0;
67+
color: @alert-font-color !important;
68+
padding: 0 0 0 10px;
6869
background-color: transparent;
6970
border: 0;
7071
-webkit-appearance: none;

flask_session_tutorial/static/src/less/vars.less

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
// Colors
2-
@theme-color: #5eb9d7;
2+
@theme-color: #0297f6;
33
@background-color: #e1eaf5;
44
@box-shadow: 0 0 5px rgba(65, 67, 144, 0.15);
55
@header-color: #5f6988;
66

7+
@alert-font-color: #856404;
8+
@alert-background-color: #fff3cd;
9+
@alert-border-color: #ffeeba;
10+
711
// Fonts
812
@body-font: 'Poppins', sans-serif;
913

0 commit comments

Comments
 (0)