1. Installation
1.1 Creating a virtual environment
mkdir myproject cd myproject python3 -m venv venv
1.2 Access to the virtual environment
. venv/bin/activate
1.3 Installing flask
pip install Flask
2. Getting Started
2.1 Minimal Demo
Save the following code as:
from flask import Flask app = Flask(__name__) @("/") def hello_world(): return "<p>Hello, World!</p>"
Run the above code:
export FLASK_APP=hello flask run
Visiting this way: http://127.0.0.1:5000 will see Hello, World!
2.2 Basic knowledge
Here are the basics of flask (a very important foundation that you can read for yourself:link (on a website)
Escaping (utilizing Jinja, cf:link (on a website)
(a few examples below)
@('/') def index(): return 'Index Page' @('/hello') def hello(): return 'Hello, World' @('/user/<username>') def show_user_profile(username): # show the user profile for that user return f'User {escape(username)}' @('/post/<int:post_id>') def show_post(post_id): # show the post with the given id, the id is an integer return f'Post {post_id}' @('/path/<path:subpath>') def show_subpath(subpath): # show the subpath after /path/ return f'Subpath {escape(subpath)}'
Methods
@('/login', methods=['GET', 'POST']) def login(): if == 'POST': else:
Files (url_for('static', filename='')
)
Templates (refer to Jinja for this one)
Uploads, Cookies, Redirects and Errors, About Responses, APIs with JSON, Sessions, Message Flashing, Logging, etc. We'll come back to them when we actually use them.
3. Deconstructing the official website guide Demo
Section 1 shows you how to quickly build a flask environment using the python virtual environment; Section 2 takes you through a brief familiarization with the programming rules (or style) of flask.
When you start this section, make sure you follow the code in section 2 to the official website! Because, instead of building a flask server step-by-step, we're going to analyze this section by taking what we've built and analyzing it in reverse.
3.1 Cloning and Code Architecture Analysis
$ git clone /pallets/flask $ cd flask $ cd examples/tutorial
The code directory structure is as follows:
3.2 Entry files
def create_app(test_config=None): """Create and configure an instance of the Flask application.""" # 1-Creating a Flask Instance # and set up some parameters that the APP will need app = Flask(__name__, instance_relative_config=True) .from_mapping( # a default secret that should be overridden by instance config SECRET_KEY="dev", # store the database in the instance folder DATABASE=(app.instance_path, ""), ) # 2-Tested if test_config is None: # load the instance config, if it exists, when not testing .from_pyfile("", silent=True) else: # load the test config if passed in (test_config) # 3-Create a folder to store files generated by the DB runtime. # ensure the instance folder exists try: (app.instance_path) except OSError: pass @("/hello") def hello(): return "Hello, World!" # register the database commands # 3.3 Database setup (add a new init_db command for flask so that hitting flask init_db directly will generate the table) from flaskr import db db.init_app(app) # apply the blueprints to the app # #### 3.4 Blueprints and views (managing organizational views based on blueprints, views registered to blueprints, blueprints registered to applications) from flaskr import auth, blog app.register_blueprint() app.register_blueprint() # make url_for('index') == url_for('') # in another app, you might define a separate main index here with # , while giving the blog blueprint a url_prefix, but for # the tutorial the blog will be the main index app.add_url_rule("/", endpoint="index") return app
3.3 Database setup
The project uses SQLite as the database (Python is built-in, eliminating installation and configuration work).
file
SQLite data is stored in tables, and you need to create a table before adding, deleting, or retrieving data from the table. In this project, we wrote SQL statements to create tables. A user table and a post table are created.
DROP TABLE IF EXISTS user; DROP TABLE IF EXISTS post; CREATE TABLE user ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password TEXT NOT NULL ); CREATE TABLE post ( id INTEGER PRIMARY KEY AUTOINCREMENT, author_id INTEGER NOT NULL, created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, title TEXT NOT NULL, body TEXT NOT NULL, FOREIGN KEY (author_id) REFERENCES user (id) );
2) Connecting and disconnecting from the database
def get_db(): """Connect to the application's configured database. The connection is unique for each request and will be reused if this is called again. """ if "db" not in g: = ( current_app.config["DATABASE"], detect_types=sqlite3.PARSE_DECLTYPES ) .row_factory = return def close_db(e=None): """If this request connected to the database, close the connection. """ db = ("db", None) if db is not None: ()
g is a special structure that is generated for each request.
3) Database initialization (table generation)
Section 1 is about building tables, so how do you execute the table building commands in that section? This is what init_db does.
def init_db(): """Clear existing data and create new tables.""" db = get_db() # Get the database (create it if it doesn't exist) # Read the SQL commands in and execute the SQL commands with the with current_app.open_resource("") as f: (().decode("utf8"))
4) Register init_db as a flask command
Since the database initialization doesn't need to be run every time the database is started (it's not a function that needs to be executed at runtime), we need to register it as a flask command by simply typingflask init-db
It will be possible to implementinit_db
The method of its realization is as follows:
@("init-db") @with_appcontext def init_db_command(): """Clear existing data and create new tables.""" init_db() ("Initialized the database.") def init_app(app): """Register database functions with the Flask app. This is called by the application factory. """ app.teardown_appcontext(close_db) # Call this function when cleaning up after returning a response .add_command(init_db_command) # Add a new command that can be called with the flask command
Thus, after execution, the file will appear in the instance folder.
3.4 Blueprints and views
A blueprint is a way to organize a set of related views and other code. Instead of registering views and other code directly with the application, they register with the blueprint. The blueprint is then registered with the application when it becomes available in the factory function.
There are two blueprints in the project: auth and blog.
bp = Blueprint("auth", __name__, url_prefix="/auth") # in bp = Blueprint("blog", __name__) # in
The parameters are: the name of the blueprint, import_name (usually __name__), and the url prefix.
[1]. Official Demo Github Repository
1) auth view
There are three main routes here:
@("/register", methods=("GET", "POST")) def register(): ... @("/login", methods=("GET", "POST")) def login(): ... @("/logout") def logout():
2) Blog View
There are four main routes here:
@("/") def index(): ... @("/create", methods=("GET", "POST")) @login_required def create(): ... @("/<int:id>/update", methods=("GET", "POST")) @login_required def update(id): ... @("/<int:id>/delete", methods=("POST",)) @login_required def delete(id): ...
3) Introduction to the implementation of each function in the registration view
enrollment
The registration logic is: first get username and password from POST, then call the database insert operation:
username = ["username"]
password = ["password"]
("INSERT INTO user (username, password) VALUES (?, ?)", (username, generate_password_hash(password)),)
log in
The login logic is: first get username and password from POST, then call the database query operation to get the user's password, and then do the password matching:
user = ("SELECT * FROM user WHERE username = ?",username,)).fetchone()
check_password_hash(user["password"], password)
After the password is matched, a session needs to be created:
if error is None: # store the user id in a new session and return to the index () session["user_id"] = user["id"] return redirect(url_for("index"))
deregister
Logging out requires clearing the session:
()
Session
The session logic is as follows: register a method to execute before any URL request, and do session management in it:
@bp.before_app_request def load_logged_in_user(): user_id = ('user_id') if user_id is None: = None else: = get_db().execute( 'SELECT * FROM user WHERE id = ?', (user_id,) ).fetchone()
Other View Usage Authentication
What should I do if other Views also want to use authentication? Implement the login_required function in to determine if the user is null, if it is null, then jump to the login page:
def login_required(view): @(view) def wrapped_view(**kwargs): if is None: return redirect(url_for('')) return view(**kwargs) return wrapped_view
4) Introduction to the implementation of each function in the blog view
Show all blogs
The logic is as follows: perform a database query operation to get all the blogs and then load them:
@("/") def index(): """Show all the posts, most recent first.""" db = get_db() posts = ( "SELECT , title, body, created, author_id, username" " FROM post p JOIN user u ON p.author_id = " " ORDER BY created DESC" ).fetchall() return render_template("blog/", posts=posts)
Create a blog
The logic is as follows: the function is preceded by@login_required
prefix, so that it can automatically determine whether it has been logged in or not, otherwise jump to the login page; create a blog is to get the title and content, and then call the insert command to insert:
@("/create", methods=("GET", "POST")) @login_required def create(): """Create a new post for the current user.""" if == "POST": title = ["title"] body = ["body"] error = None if not title: error = "Title is required." if error is not None: flash(error) else: db = get_db() ( "INSERT INTO post (title, body, author_id) VALUES (?, ?, ?)", (title, body, ["id"]), ) () return redirect(url_for("")) return render_template("blog/")
Updating and deleting blogs
For updating and deleting blogs, you need to pass in an id, and then there is an internal function to determine if that id exists:
def get_post(id, check_author=True): """Get a post and its author by id. Checks that the id exists and optionally that the current user is the author. :param id: id of post to get :param check_author: require the current user to be the author :return: the post with author information :raise 404: if a post with the given id doesn't exist :raise 403: if the current user isn't the author """ post = ( get_db() .execute( "SELECT , title, body, created, author_id, username" " FROM post p JOIN user u ON p.author_id = " " WHERE = ?", (id,), ) .fetchone() ) if post is None: abort(404, f"Post id {id} doesn't exist.") if check_author and post["author_id"] != ["id"]: abort(403) return post
Therefore, the logic of the update is as follows:
@("/<int:id>/update", methods=("GET", "POST")) @login_required def update(id): """Update a post if the current user is the author.""" post = get_post(id) if == "POST": title = ["title"] body = ["body"] error = None if not title: error = "Title is required." if error is not None: flash(error) else: db = get_db() ( "UPDATE post SET title = ?, body = ? WHERE id = ?", (title, body, id) ) () return redirect(url_for("")) return render_template("blog/", post=post)
The logic for deletion is as follows:
@("/<int:id>/delete", methods=("POST",)) @login_required def delete(id): """Delete a post. Ensures that the post exists and that the logged in user is the author of the post. """ get_post(id) db = get_db() ("DELETE FROM post WHERE id = ?", (id,)) () return redirect(url_for(""))
4. Other
There are others that people need to see after they've played with it:
- Engineering Deployment Installation
- Engineering Automation Testing
5. Run up DEMO
Finally, let's run the demo to see how it works:
1) In the tutorial directory, create a virtual environment and install Flask:
python3 -m venv venv . venv/bin/activate pip install Flask
2) Run as a developer:
export FLASK_APP=flaskr export FLASK_ENV=development flask init-db flask run
The effect is as follows:
The above is a detailed explanation of the installation and application of Python Flask framework in detail, more information about Python Flask framework please pay attention to my other related articles!