Skip to content

Commit fd77248

Browse files
committed
initial copy from official flask repo
0 parents  commit fd77248

24 files changed

+1034
-0
lines changed

.gitignore

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
venv/
2+
*.pyc
3+
__pycache__/
4+
instance/
5+
.cache/
6+
.pytest_cache/
7+
.coverage
8+
htmlcov/
9+
dist/
10+
build/
11+
*.egg-info/
12+
.idea/
13+
*.swp
14+
*~

LICENSE.rst

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Copyright 2010 Pallets
2+
3+
Redistribution and use in source and binary forms, with or without
4+
modification, are permitted provided that the following conditions are
5+
met:
6+
7+
1. Redistributions of source code must retain the above copyright
8+
notice, this list of conditions and the following disclaimer.
9+
10+
2. Redistributions in binary form must reproduce the above copyright
11+
notice, this list of conditions and the following disclaimer in the
12+
documentation and/or other materials provided with the distribution.
13+
14+
3. Neither the name of the copyright holder nor the names of its
15+
contributors may be used to endorse or promote products derived from
16+
this software without specific prior written permission.
17+
18+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24+
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

MANIFEST.in

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
include LICENSE.rst
2+
include flaskr/schema.sql
3+
graft flaskr/static
4+
graft flaskr/templates
5+
graft tests
6+
global-exclude *.pyc

README.rst

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
Flaskr
2+
======
3+
4+
The basic blog app built in the Flask `tutorial`_.
5+
6+
.. _tutorial: https://flask.palletsprojects.com/tutorial/
7+
8+
9+
Install
10+
-------
11+
12+
**Be sure to use the same version of the code as the version of the docs
13+
you're reading.** You probably want the latest tagged version, but the
14+
default Git version is the main branch. ::
15+
16+
# clone the repository
17+
$ git clone https://github.com/pallets/flask
18+
$ cd flask
19+
# checkout the correct version
20+
$ git tag # shows the tagged versions
21+
$ git checkout latest-tag-found-above
22+
$ cd examples/tutorial
23+
24+
Create a virtualenv and activate it::
25+
26+
$ python3 -m venv venv
27+
$ . venv/bin/activate
28+
29+
Or on Windows cmd::
30+
31+
$ py -3 -m venv venv
32+
$ venv\Scripts\activate.bat
33+
34+
Install Flaskr::
35+
36+
$ pip install -e .
37+
38+
Or if you are using the main branch, install Flask from source before
39+
installing Flaskr::
40+
41+
$ pip install -e ../..
42+
$ pip install -e .
43+
44+
45+
Run
46+
---
47+
48+
::
49+
50+
$ export FLASK_APP=flaskr
51+
$ export FLASK_ENV=development
52+
$ flask init-db
53+
$ flask run
54+
55+
Or on Windows cmd::
56+
57+
> set FLASK_APP=flaskr
58+
> set FLASK_ENV=development
59+
> flask init-db
60+
> flask run
61+
62+
Open http://127.0.0.1:5000 in a browser.
63+
64+
65+
Test
66+
----
67+
68+
::
69+
70+
$ pip install '.[test]'
71+
$ pytest
72+
73+
Run with coverage report::
74+
75+
$ coverage run -m pytest
76+
$ coverage report
77+
$ coverage html # open htmlcov/index.html in a browser

flaskr/__init__.py

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import os
2+
3+
from flask import Flask
4+
5+
6+
def create_app(test_config=None):
7+
"""Create and configure an instance of the Flask application."""
8+
app = Flask(__name__, instance_relative_config=True)
9+
app.config.from_mapping(
10+
# a default secret that should be overridden by instance config
11+
SECRET_KEY="dev",
12+
# store the database in the instance folder
13+
DATABASE=os.path.join(app.instance_path, "flaskr.sqlite"),
14+
)
15+
16+
if test_config is None:
17+
# load the instance config, if it exists, when not testing
18+
app.config.from_pyfile("config.py", silent=True)
19+
else:
20+
# load the test config if passed in
21+
app.config.update(test_config)
22+
23+
# ensure the instance folder exists
24+
try:
25+
os.makedirs(app.instance_path)
26+
except OSError:
27+
pass
28+
29+
@app.route("/hello")
30+
def hello():
31+
return "Hello, World!"
32+
33+
# register the database commands
34+
from flaskr import db
35+
36+
db.init_app(app)
37+
38+
# apply the blueprints to the app
39+
from flaskr import auth, blog
40+
41+
app.register_blueprint(auth.bp)
42+
app.register_blueprint(blog.bp)
43+
44+
# make url_for('index') == url_for('blog.index')
45+
# in another app, you might define a separate main index here with
46+
# app.route, while giving the blog blueprint a url_prefix, but for
47+
# the tutorial the blog will be the main index
48+
app.add_url_rule("/", endpoint="index")
49+
50+
return app

flaskr/auth.py

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import functools
2+
3+
from flask import Blueprint
4+
from flask import flash
5+
from flask import g
6+
from flask import redirect
7+
from flask import render_template
8+
from flask import request
9+
from flask import session
10+
from flask import url_for
11+
from werkzeug.security import check_password_hash
12+
from werkzeug.security import generate_password_hash
13+
14+
from flaskr.db import get_db
15+
16+
bp = Blueprint("auth", __name__, url_prefix="/auth")
17+
18+
19+
def login_required(view):
20+
"""View decorator that redirects anonymous users to the login page."""
21+
22+
@functools.wraps(view)
23+
def wrapped_view(**kwargs):
24+
if g.user is None:
25+
return redirect(url_for("auth.login"))
26+
27+
return view(**kwargs)
28+
29+
return wrapped_view
30+
31+
32+
@bp.before_app_request
33+
def load_logged_in_user():
34+
"""If a user id is stored in the session, load the user object from
35+
the database into ``g.user``."""
36+
user_id = session.get("user_id")
37+
38+
if user_id is None:
39+
g.user = None
40+
else:
41+
g.user = (
42+
get_db().execute("SELECT * FROM user WHERE id = ?", (user_id,)).fetchone()
43+
)
44+
45+
46+
@bp.route("/register", methods=("GET", "POST"))
47+
def register():
48+
"""Register a new user.
49+
50+
Validates that the username is not already taken. Hashes the
51+
password for security.
52+
"""
53+
if request.method == "POST":
54+
username = request.form["username"]
55+
password = request.form["password"]
56+
db = get_db()
57+
error = None
58+
59+
if not username:
60+
error = "Username is required."
61+
elif not password:
62+
error = "Password is required."
63+
64+
if error is None:
65+
try:
66+
db.execute(
67+
"INSERT INTO user (username, password) VALUES (?, ?)",
68+
(username, generate_password_hash(password)),
69+
)
70+
db.commit()
71+
except db.IntegrityError:
72+
# The username was already taken, which caused the
73+
# commit to fail. Show a validation error.
74+
error = f"User {username} is already registered."
75+
else:
76+
# Success, go to the login page.
77+
return redirect(url_for("auth.login"))
78+
79+
flash(error)
80+
81+
return render_template("auth/register.html")
82+
83+
84+
@bp.route("/login", methods=("GET", "POST"))
85+
def login():
86+
"""Log in a registered user by adding the user id to the session."""
87+
if request.method == "POST":
88+
username = request.form["username"]
89+
password = request.form["password"]
90+
db = get_db()
91+
error = None
92+
user = db.execute(
93+
"SELECT * FROM user WHERE username = ?", (username,)
94+
).fetchone()
95+
96+
if user is None:
97+
error = "Incorrect username."
98+
elif not check_password_hash(user["password"], password):
99+
error = "Incorrect password."
100+
101+
if error is None:
102+
# store the user id in a new session and return to the index
103+
session.clear()
104+
session["user_id"] = user["id"]
105+
return redirect(url_for("index"))
106+
107+
flash(error)
108+
109+
return render_template("auth/login.html")
110+
111+
112+
@bp.route("/logout")
113+
def logout():
114+
"""Clear the current session, including the stored user id."""
115+
session.clear()
116+
return redirect(url_for("index"))

0 commit comments

Comments
 (0)