Request sends HTTP requests.
BeautifulSoup scrapes Web pages.
SQLAlchemy is a SQL Toolkit.
PyTest is a testing framework.
Predefined structures for application development.
Provides a set of guidelines for application development.
Ex: Django, Flask, ans Web2Py.
Code call library.
Framework calls code.
Framework can contain libraries.
Flask is a micro web framework.
Created in 2004 by Armin Ronacher.
Comes with a minimal ser of dependencies.
Community-maintained extensions.
Built-in Web server.
Has a debugger.
Uses standard Python logging.
Has built-in unit testing.
Enables request and response classes.
Provide static ass support
Provide dynamin templates.
Support routing:
Dynamic URLs
HTTP Methods.
Redirecting.
Enables error handling.
Support sessions.
Flask-SQLAlchemy: Database objects
Flask-Mail: Setup an SMTP mail server.
Flask-Admin: add interfaces to Flask applications easily.
Flask-Uploads: Customize file uploading to the application.
Flask-CORS: Handle Cross-Origin Resource Sharing.
Flask-Migrate.
Flask-User.
Marshmallow.
Celery.
pip install Flask=2.2.2
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return "<b> My first Flask application in action! </b>"
To run the application, in the terminal:
export FLASK_APP=app.py
export FLASK_ENV=development
flask run -p 4999
from flask import Flask
from flask import jsonify
app = Flask(__name__)
@app.route('/')
def index():
return jsonify(message="Hello, World! This is a Flask App")
ENV
DEBUG
TESTING
SECRET_KEY
SESSION_COOKIE_NAME
SERVER_NAME
JSONIFY_MIMETYPE
Flask provides a config object that acts like a dictionary.
app.config['SECRET_KEY'] = "random-secret-key"
Configure from an environment variable
app.config["VARIABLE_NAME"]
app.config.from_prefixed_env()
Configure from a python file
app.config.from_file("pathtoconfigfile")
Main Application Python Module.
Configuration File.
Static Files Folder.
Templates Folder.
Testing Folder.
Virtual Environment.
@app.route("/path") decorates defaults to get the GET method.
Use methods argument to only allow specific HTTP methods.
Two methods below are the same:
@app.route("/health")
def health():
return jsonify(dict(status = "OK")), 200
@app.route("/health", methods = ["GET"])
def health():
return jsonify(dict(status = "OK")), 200
Flask.Request All HTTP calls to Flask contain the request object.
Some common request attributes are:
server
headers
URL
access_route
full_path
is_sucure
is_JSON
cookies
The header contains the following data:
Cache-Control
Accept
Accept-Encoding
User-Agent
Accept-Language
Host
Methods:
get_data: Get POST data from the request as bytes.
get_JSON: Parses POST data from the request as JSON.
Parse request data:
args.
JSON.
files.
form.
values.
@app.route('/')
def hello_world():
course = request.args['course']
rating = request.args.get('rating')
return {"message": f"{course} with rating {rating}"}
# run by: http://127.0.0.1:4999/?course=phongphu&rating=10
Some common response attributes are:
status_code.
headers.
content_type.
content_length.
content_encoding.
mimetype.
expires.
Some common methods of response objects:
set_cookie.
delete_cookie.
Can call external APIs using the Python request library
Return JSON as a dictionary to the caller.
Parameter types validate requests.
@app.route("terminals/<string:airport_code>")
@app.route('/book/<int:isbn>')
Every response contains a three-digit integer status code.
Valid responses range from 100 to 599.
400 indicates an invalid request. This status could imply the parameters are missing or improper or the request is invalid in another way.
401 indicates the credentials are missing or invalid.
403 implies that the client credentials are not sufficient to fulfill the request. If the server is unable to find the resource, it returns a 404 status.
405 indicates that the requested operation is not supported.
500 is used when there is an error on the server.
Return tuple with response as first valua and status as the second value.
@app.route('/')
def hello_world():
return ("<b> My firs Flask app" </b>", 200)
Use the make_response() method
@app.route("/")
def hello_world():
res = make_response("<b> My first Flask app </b>")
res.status_code = 200
return res
Serve static HTML Pages.
Serve dynamic HTML Pages.
Passing arguments.
def jsonify_decorator(function):
def modifyOutput():
return {"output": function()}
return modifyOutput
@app.route("/userdetails/<userid>")
def getUserIdDetails(userid):
return "User Details for " + userid
Create, Read, Update, and Delete (CRUD) are basic functions that any application with a database must perform. To effectively implement the CRUD operations, you will need to manage different HTTP methods, such as GET and POST requests.
A GET request is generally used to retrieve or read data and is often used to display a form.
A POST request is commonly used to send data to create or update data. An example of a POST request is form submission.
You can use flask.request.form to access form data that a user has submitted via a POST request.
For instance, this feature can be used if you have a login form with username and password fields.
In your HTML file, you might have a form like this:
<form method="POST" action="/login">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="Submit">
</form>
The Python code to access the username and password will be as follows:
from flask import request
@app.route('/login', methods=['POST'])
def login():
username = request.form['username']
password = request.form['password']
# process login here
Flask provides a function called flask.redirect to guide users to a different webpages (or endpoints).
The flask.redirect function can be useful in several scenarios.
For example, you can use the flask.redirect function to redirect a user to a login page when they try to access a restricted admin page.
from flask import redirect
@app.route('/admin')
def admin():
return redirect('/login')
The flask.url_for function dynamically generates URLs for a given endpoint. Dynamically generating URLs can be particularly useful when the URL for a route is altered.
The flask.url_for function automatically updates the URL throughout your templates or code, minimizing manual work.
For example, consider the scenario where a user is trying to access the admin page and must be redirected to the login page. In this scenario, url_for('login') will retrieve the URL for the login page from the existing routes.
from flask import url_for
@app.route('/admin')
def admin():
return redirect(url_for('login'))
@app.route('/login')
def login():
return "<Login Page>"
You can define the route with both the access methods, GET and POST, and in the function description, define the use cases for both methods.
@app.route('/data', methods=['GET', 'POST'])
def data():
if request.method == 'POST':
# process POST request
if request.method == 'GET':
# process GET request
In the HTML file, you will add a form that allows both GET and POST requests:
<!-- For POST -->
<form method="POST" action="/data">
<!-- Your input fields here -->
<input type="submit" value="Submit">
</form>
<!-- For GET -->
<a href="/data">Fetch data</a>
The /data route accepts both GET and POST requests. The type of the request can be checked using flask.request.method.
Creating data often involves presenting a form to the user to gather the information that you want to store in the database as a new record. In Flask, this data is accessed using flask.request.form.
HTML form for creating data:
<form method="POST" action="/create">
<input type="text" name="name">
<input type="submit" value="Create">
</form>
Python code:
@app.route('/create', methods=['GET', 'POST'])
def create():
if request.method == 'POST':
# Access form data
name = request.form['name']
# Create a new record with the name
record = create_new_record(name) # Assuming you have this function defined
# Redirect user to the new record
return redirect(url_for('read', id=record.id))
# Render the form for GET request
return render_template('create.html')
Reading data involves accessing the data and presenting it to the user. To access specific entries, the request needs to go with specific IDs. Therefore, you will need to pass the ID as an argument to the function. The following example shows that the ID can be accessed from the route.
Python code:
@app.route('/read/<int:id>', methods=['GET'])
def read(id):
# Get the record by id
record = get_record(id) # Assuming you have this function defined
# Render a template with the record
return render_template('read.html', record=record)
Updating data requires the process of accessing specific entries, like the Read operation, and involves giving new data to the concerned parameter, like the Create operation. Therefore, the route should access the ID and contain both access methods.
Sample HTML form for updating data:
<form method="POST" action="/update/{{record.id}}">
<input type="text" name="name" value="{{record.name}}">
<input type="submit" value="Update">
</form>
Python code:
@app.route('/update/<int:id>', methods=['GET', 'POST'])
def update(id):
if request.method == 'POST':
# Access form data
name = request.form['name']
# Update the record with the new name
update_record(id, name) # Assuming you have this function defined
# Redirect user to the updated record
return redirect(url_for('read', id=id))
# Render the form for GET request with current data
record = get_record(id) # Assuming you have this function defined
return render_template('update.html', record=record)
Deleting data involves removing a record based on its ID. The Delete operation will typically require the ID to be passed, as reported by the HTML page, in the form of an argument to the function.
Sample HTML form for deleting data:
<form method="POST" action="/delete/{{record.id}}">
<input type="submit" value="Delete">
</form>
Python code:
@app.route('/delete/<int:id>', methods=['POST'])
def delete(id):
# Delete the record
delete_record(id) # Assuming you have this function defined
# Redirect user to the homepage
return redirect(url_for('home'))