You are on page 1of 59

CO-2

1. INTRODUCTION TO WEB
The Web is the common name for the World Wide Web, a subset of the Internet
consisting of the pages that can be accessed by a Web browser. Many people assume that
the Web is the same as the Internet, and use these terms interchangeably. However, the
term Internet actually refers to the global network of servers that makes the information
sharing that happens over the Web possible. So, although the Web does make up a large
portion of the Internet, but they are not one and same. Web pages are formatted in a
language called Hypertext Markup Language (HTML). It this language that allows users
to click through pages on the Web via links. The Web uses HTTP protocol to transmit
data and share information. Browsers such as Internet Explorer, Google Chrome or
Mozilla Firefox are used to access Web documents, or Web pages, which are connected
via links. The Web is just one of the ways that information is shared over the Internet;
others include email, instant messaging and File Transfer Protocol (FTP).
2. KEY FEATURES OF WEB
1. Quality Web Content. There’s one primary reason people use search engines and
browse websites, and that is to search for information. People desire information
every day, and want if delivered in a fast and reliable fashion. Whether to entertain,
entice or educate, superior content is a must in every frequently visited website,
especially if search engine optimisation is part of the website's overarching marketing
strategy.
For business websites, content should include important information and come in the
forms that are pertinent to the business. Retail sites for example, need high quality
pictures of their products, while consulting firms are more apt to highlight client
testimonials. A best practice for most search engine optimisation gurus is also
ensuring the most relevant content is prominent on the webpages.
2. Clear, User-friendly Navigation. A stellar web design must contain a user-friendly
navigation scheme that allows visitors to quickly find the information needed.
Important links must be easy to find and given logical, simple, and include easy-to-
understand labels. Calls to action are placed in conspicuous spots within the
navigation’s scheme. If there is a plethora of content, then a search box is suggested
to make it faster to reach more specific pages within a website.
3. Simple and Professional Web Design. Bells and whistles may seem nice in concept,
but they rarely add much value to an effectively constructed and sensible web design.
Typically, the websites best at effectively converting site visitors into buying
customers, maintain an attractive layout, but keep it clean and simple. Google is an
excellent example of such a site. Actually, users found Google’s initial design over
simplified during the initial testing phases. 1.Thus, in order to keep a simple interface,
but prevent the appearance of site constructed without much thought, Google added
the ‘I’m Feeling Lucky’ button underneath the search box. Despite the fact that hardly
anyone clicks on this button, its addition balances the layout in such a way that
delivers a better user experience.
To keep websites simple, without making them look bland such as in Google’s case, a
balanced distribution of content and graphics is required and the use of slightly
contrasting colors and clear fonts is key. Visit
http://www.thewebshowroom.com.au/balancing-web-graphics-text/ for more
information on balancing graphics and content in any site's web design. Colors that
are scream, are overtly contrasting, and font sizes that are difficult to read will put a
strain on visitors’ eyes. Also, one should break up sizeable blocks of text with either
spacing or images as appropriate.
4. Webpage Speed. People inherently lose patience quickly, and that holds true when
visiting a website. The longer a website takes to load, the more likely a person will
leave before it fully renders. Beautiful graphics and substantial content become
useless if a site’s speed hampers its ability to deliver content quickly.
Several factors affect site speed, including server speed, the number of graphics,
website traffic, etc. A web design company must make sure to minimize all
controllable factors slowing down site speed by using reliable site hosting, proper
website code, and optimized graphics.
5. Search Engine Optimization. A well-designed website generally will receive many
visitors, and one method to attract visitors is search engine optimization. This entails
the insertion of search keywords in website content, an appropriate link profile, social
media signals, and over 200 other factors. Just as The Web Showroom developed a
resources section for web design, we also created a search engine optimization
resources to help company's improve their rankings.
6. Web Compatibility. The variety of browser and platforms which one can now be
view web design can present a challenge to developers, but talented ones are
accustomed to handling such factors. A site should easily render on various
resolutions, screen sizes, and browsers; and with the increasing popularity of mobile
devices, websites should function properly on the plethora of these types of devices.
When it comes to web design, remember that not all that glitters is gold. Know what truly
makes a well-built site and you’ll soon find your website quickly on its way to attracting
and retaining customers.

KEY TERMS IN WEB


User: As the name implies, the term "user" simply refers to anyone who will be using the
site you're making. Some other industries might call it a "customer" or "client" but it's a
good idea to start being consistent and only using the term "user" when referring to the,
well, users on your site.
Usability: If a website is hard to use, people will abandon it. You want your site to retain
users, of course, so the term "usability" refers to how easy it is to use and navigate for an
average person.
User Interface (UI): The user interface is simply how a user interacts with the design on
a page. For example, the battery indicator on your smart phone is a part of the user
interface. Sometimes UI is lumped with UX, which includes how pretty the site is, the
site's response time, and site content.
User Experience (UX or UXD): User Experience, or User Experience Design, as it's
sometimes called, focuses on the human interaction with the computer or device. For
example, the action that happens if you were to tap the battery indicator on your phone is
a part of the user experience. So, while the UI is the design of something that your users
will interact with, the UX is what will happen when the interaction actually takes place.
Responsive Design: The term responsive design refers to a specific design technique in
which your site will shift around by using grids and flexible images. The goal is so it'll
rearrange itself depending on the screen size the user is using while still keeping a great
user experience across all devices. This is often how a site will look different on your
phone than on your computer.
Wireframe: A wireframe is an outline used to plan a site's structure and functionality. It
usually starts hand-drawn on paper and then created in grayscale in program like
Photoshop or Illustrator without any design elements like color, photos or typography.
Places where text content would be is also replaced with Lorem Ipsum (or dummy) text.
Frameworks: A framework provides a foundation that developers can use to build
programs and streamline the development process. They help you add extra functionality
to your site without having to start from scratch or create a simple feature that could take
you hours to write.
Text Editor: Until developers can figure out a way to magically create code, text editors
are the program-of-choice for actually writing code, much in the same way you might use
Microsoft Word as your go-to for writing documents. There are dozens of options
available that all have time-saving features.
HTML: Whether or not you’re new to web design, you've probably heard the term
“HTML”. What you may not know is that HTML is an acronym that stands for Hypertext
Mark-up Language. HTML is a computer language used by your browser to display your
site to the user. Since just about all websites are displayed in a browser, HTML is the
backbone of any website.
CSS: CSS is another abbreviation which stands for Cascading Style Sheets. CSS works
hand-in-hand with HTML to create sites that are more than plain text. If HTML is the
backbone, then CSS is the skin, the hair and the style of clothes. You’ll use CSS to tell
the browser things like what color your text should be and what fonts to display.
Front-End: The front-end of a website refers to part of the site that your user interacts
with directly. Coding languages like HTML and CSS are parts of the site that encompass
the front-end because they’re the languages that your user’s browser reads. If you think of
your website like a restaurant, the front-end is your server, the menus and the decorations,
basically anything you, the customer, can see and interact with.
Back-End: The back-end of a website is everything that the user can't see and interact
with. Typically back-end coding languages like PHP or .NET are run on a server. For this
reason, the back-end code is also sometimes referred to as server-side code. So if we're
sticking with the restaurant example from above, the back-end is the kitchen and cooks.
The kitchen and cooks are out of your view, but they're still there making the food and are
obviously important to the functionality of the restaurant. Similarly, a functional website
needs a strong back-end to interact with the front-end in order to be successful. In
conclusion So that’s a look at some of the more common web design terms you'll see in
the web world. If you want to dive in a little deeper and see how these terms can play
together to make a functioning website, check out our "Your First Day with HTML"
course and use this as a handy reference guide.
CLIENT SERVER ARCHITECTURE
What is Client Server Architecture

Definition – Client-server architecture is also called of the “Client/Server Network” or


“Network computing Model“, because in this architecture all services and requests are
spread over the network. Its functionality like as distributed computing system because in
which all components are performing their tasks independently from each other.

Client-server architecture is a shared computer network architecture where several clients


(remote system) send many requests and finally to obtained services from the centralized
server machine (host system). Client machine delivers user-friendly interface that helps to
users to fire request services of server computer and finally to show your output on client
system.

Diagram of Client Server Architecture

1-Tier Architecture
In the 1-tier architecture, all client/server configuration setting, user interface environment,
data logic, and marketing logic system are existed on the same system. These types of
services are reliable but it is very difficult tasks to handle because they contain all data in
different variance, which are allotted the replication of entire work. This architecture also
contains the different layers.
2-Tier Architecture
2-tier architecture provides the best client/server environment that helps to store user
interface on the client system and all database is saved on the server machine. Business logic
and database logic are existed on the client otherwise server, but they are required to be
maintained. When data logic and business are gathered on the client terminal then it is known
as “fat client thin server architecture”. But if Business Logic and Data Logic are controlled at
the server machine then it is known as “thin client fat server architecture”.

In this architecture, client and server machines are connected directly incorporation because
if client is firing any input for server terminal then in between should not any intermediate.
So, it delivers the output with fastest rate and to ignore misunderstanding between the other
clients.

Benefits Are

• Easy to design all applications


• Maximum user satisfaction
• Implementation of Homogeneous Environment
• Best performance
• Limitations Are
• Poor performance due to grow number of connections of each user
• Less security
• All clients are totally dependent upon the manufacturer’s database.
• Less portability means this architecture is totally dependent upon the particular database.

3-Tier Architecture

In this 3-tier architecture, middleware is needed because if client machine sends the request
to server machine then firstly this request is received by middle layer, and finally this request
is obtained to server. So, firstly response of server is received by middle layer then it is
obtained to client machine. All data logic and business logic are stored on the middleware.
Due to use of middleware, to improve its flexibility and deliver excellent performance.

3-tier architecture is divided into 3 layers such as presentation layer (Client Tier), Application
layer (Business Tier) and Database layer (Data Tier). Client machine handles the presentation
layer, Application layer controls the Application layer, and finally Server machine takes care
of Database layer.

Benefits Are
• Best performed data integrity
• Improved security to 2-tier architecture
• Hide database structure

Limitation is:
• To increase complexity of communication in between client and server because in which
middleware is also used

N-Tier Architecture

This architecture is also known as the “Multitier Architecture”, so it is scaled form of 3-tier
architecture. In this architecture, entire presentations, application processing, and data
management functions are isolated from each other.
Benefit is

It delivers the flexible and reusable applications.

Limitation is

Harder to implement because it uses the complex structure (componentization of tiers)

Examples of Client Server Architecture

There are four examples of Client Server Architecture. Below explain each one –

Web Servers – Web server likes as high-performance computer system that can host
multiples websites. On this server, to install different types of web server software like as
Apache or Microsoft IIS, which delivers access to hosted several websites on the internet, and
these servers are linked with internet through higher speed connection that delivers ultra data
transmission rates.

Mail Servers – Email servers helps to send and receive all emails. Some software are run on
the mail server which allow to administrator to create and handle all email accounts for any
domain that is hosted on the server. Mail servers use the some protocols for sending and
receiving emails such as SMTP, IMAP, and POP3. SMTP protocol helps to fire messages
and manages all outgoing email requests. IMAP and POP3 help to receive all messages and
handle all incoming mails.

File Servers – File server is dedicated systems that allow users to access for all files. It works
like as centralized file storage location, and it can be accessed by several terminal systems.

DNS – DNS stands for “Domain Name Server“, and it has huge database of different types of
public IP addresses, and they link with their hostnames

These types of server help to deliver all resources (like as files, directories, shared devices
such as applications and printers) to client terminal like as PCs, smart phones, PDAs, laptops,
tablets etc.
Components of Client Server Architecture

Client-server architecture contains three components such as workstations, server, and


networking devices, and they are connected with each other.

Workstation – Workstation is also known as “Client Computer“. There are different types
of operating systems, which are installed on the workstations like as Windows 2000,
Windows XP, Windows Vista, Windows 7, and Windows 10. These workstation operating
systems are cheaper compare to server’s operating systems.

Server – Server is a ultra performer computer system that contains the fastest memory, more
hard drive space, and faster speed processors because they save and service of several
requests which are coming from workstation side. A server plays different types of roles like
as mail server, database server, file server, and domain controller at the same time duration.

Network Devices – With the help of network devices; workstations and servers are
connected with each other. Every network device has own functionality like as hub is used
for making connection between server to multiple workstations, repeater is used for moving
data from one devices to another device, and bridges helps to isolate of all network segments.

FLASK FRAMEWORK

Flask is a web framework, it’s a Python module that lets you develop web
applications easily. It’s has a small and easy-to-extend core: it’s a micro framework that
doesn’t include an ORM (Object Relational Manager) or such features. It does have many
cool features like URL routing, template engine. It is a WSGI web app framework. A Web
Application Framework or a simply a Web Framework represents a collection of libraries and
modules that enable web application developers to write applications without worrying about
low-level details such as protocol, thread management, and so on. Flask is a web application
framework written in Python. It was developed by Armin Ronacher, who led a team of
international Python enthusiasts called Poocco. Flask is based on the Werkzeg WSGI toolkit
and the Jinja2 template engine.Both are Pocco projects.
WSGI

The Web Server Gateway Interface (Web Server Gateway Interface, WSGI) has been
used as a standard for Python web application development. WSGI is the specification of a
common interface between web servers and web applications.

Werkzeug

Werkzeug is a WSGI toolkit that implements requests, response objects, and utility
functions. This enables a web frame to be built on it. The Flask framework uses Werkzeg as
one of its bases.

jinja2

jinja2 is a popular template engine for Python. A web template system combines a
template with a specific data source to render a dynamic web page.

This allows you to pass Python variables into HTML templates like this:

<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>Hello {{ username }}</h1>
</body>
</html>

Unlike the Django framework, Flask is very Pythonic. It’s easy to get started with Flask,
because it doesn’t have a huge learning curve.

On top of that it’s very explicit, which increases readability. To create the “Hello World” app,
you only need a few lines of code.

This is a sample code example.

from flask import Flask


app = Flask(__name__)

@app.route('/')
def hello_world():
return 'Hello World!'

if __name__ == '__main__':
app.run()

If you want to develop on your local computer, you can do so easily. Save this program as
server.py and run it with python server.py.
python server.py

* Serving Flask app "hello"


* Running on http://127.0.0.1:5000/

FLASK INSTALLATION

As we are on Windows and we don’t have the easy install command. firstly, we have to
install it.

1. install pip

1.1 Assuming you are using Python 2.7 on the default path, so if have not add python to
your path, added it now:
C:\Python27\Scripts
1.2 Now you have easy install so we can use it to install pip by below command
easy install pip.

2. Create virtualenv environment

2.1 Install virtualenv in windows

pip install virtualenv

2.2 After virtualenv installed, we can create our own environment or browser to your
location from CMD. we usually create a project folder and a venv folder within

virtualenv venv

2.3 To activate the corresponding environment


venv\scripts\activate

you should now be using your virtualenv (notice how the prompt of your shell has changed to
show the active environment)

3. Installing Flask

The following command to get Flask activated in our virtualenv:

pip install Flask


FLASK APPLICATION STRUCTURE:

The project directory will contain:

• flaskr/, a Python package containing your application code and files.


• tests/, a directory containing test modules.
• venv/, a Python virtual environment where Flask and other dependencies are installed.
• Installation files telling Python how to install your project.
• Version control config, such as git. You should make a habit of using some type of
version control for all your projects, no matter the size.
• Any other project files you might add in the future.

By the end, your project layout will look like this:

/home/user/Projects/flask-tutorial
├── flaskr/
│ ├── __init__.py
│ ├── db.py
│ ├── schema.sql
│ ├── auth.py
│ ├── blog.py
│ ├── templates/
│ │ ├── base.html
│ │ ├── auth/
│ │ │ ├── login.html
│ │ │ └── register.html
│ │ └── blog/
│ │ ├── create.html
│ │ ├── index.html
│ │ └── update.html
│ └── static/
│ └── style.css
├── tests/
│ ├── conftest.py
│ ├── data.sql
│ ├── test_factory.py
│ ├── test_db.py
│ ├── test_auth.py
│ └── test_blog.py
├── venv/
├── setup.py
└── MANIFEST.in

If you’re using version control, the following files that are generated while running your
project should be ignored. There may be other files based on the editor you use. In general,
ignore files that you didn’t write. For example, with git:

.gitignore¶
venv/

*.pyc
__pycache__/

instance/

.pytest_cache/
.coverage
htmlcov/

dist/
build/
*.egg-info/

Phases in Flask Application Creation


The code lets us run a basic web application that we can serve, as if it were a website.
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return "Hello, World!"

if __name__ == "__main__":
app.run(debug=True)

This piece of code is stored in our main.py.


In your Terminal or Command Prompt go to the folder that contains your main.py. Then do
py main.py or python main.py. In your terminal or command prompt you should see this
output.

The important part is where it says Running on http://127.0.0.1:5000/.

127.0.0.1 means this local computer. Go to that address and you should see the following:
Congrats! You made a website with Flask!

Now add app.route(“/”).

from flask import Flask

app = Flask(__name__)

@app.route("/")
def home():
return "Hello, World!"

@app.route("/salvador")
def salvador():
return "Hello, Salvador"

if __name__ == "__main__":
app.run(debug=True)
Now run the main.py again and go to http://localhost:5000/salvador.

Adding HTML and Templates in Flask

First create a new HTML file. I called mine home.html.

Here is some code to get you started.

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Flask Tutorial</title>
</head>
<body>
<h1> My First Try Using Flask </h1>
<p> Flask is Fun </p>
</body>
</html>
The Flask Framework looks for HTML files in a folder called templates. You need to create
a templates folder and put all your HTML files in there.

Remember to always keep the main.py outside of your templates folder

Now we need to change our main.py so that we can view the HTML file we created.

from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def home():
return render_template("home.html")

@app.route("/salvador")
def salvador():
return "Hello, Salvador"

if __name__ == "__main__":
app.run(debug=True)
Add more pages

Create about.html inside the templates folder.

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>About Flask</title>
</head>
<body>
<h1> About Flask </h1>
<p> Flask is a micro web framework written in Python.</p>
<p> Applications that use the Flask framework include Pinterest,
LinkedIn, and the community web page for Flask itself.</p>
</body>
</html>
Let’s make a change similar to what we did before to our main.py.

from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def home():
return render_template("home.html")

@app.route("/about)
def about():
return render_template("about.html")

if __name__ == "__main__":
app.run(debug=True)
We made three new changes:

Connect Both Pages with a Navigation

To connect both pages we can have a navigation menu on the top. We can use Flask to make
the process of creating a navigation menu easier.

First, let’s create a template.html. This template.html will serve as a parent template. Our
two child templates will inherit code from it.

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Flask Parent Template</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/template.css') }}">
</head>
<body>
<header>
<div class="container">
<h1 class="logo">First Web App</h1>
<strong><nav>
<ul class="menu">
<li><a href="{{ url_for('home') }}">Home</a></li>
<li><a href="{{ url_for('about') }}">About</a></li>
</ul>
</nav></strong>
</div>
</header>
{% block content %}
{% endblock %}

</body>
</html>
Copy the code for the navigation menu in the about.html and home.html.

Content of about.html:

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>About Flask</title>
</head>
<body>
{% extends "template.html" %}
{% block content %}

<h1> About Flask </h1>


<p> Flask is a micro web framework written in Python.</p>
<p> Applications that use the Flask framework include Pinterest,
LinkedIn, and the community web page for Flask itself.</p>

{% endblock %}
</body>
</html>
Content of home.html:

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Flask Tutorial</title>
</head>
<body>
{% extends "template.html" %}
{% block content %}
<h1> My First Try Using Flask </h1>
<p> Flask is Fun </p>

{% endblock %}
</body>
</html>
Adding CSS to Our Website

An important note to remember

In the same way as we created a folder called templates to store all our HTML templates, we
need a folder called static.

In static, we will store our CSS, JavaScript, images, and other necessary files. That is why it
is important that you should create a CSS folder to store your stylesheets. After you do this,
your project folder should look like this:

Linking our CSS with our HTML file

Our template.html is the one that links all pages. We can insert the code here and it will be
applicable to all child pages.

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Flask Parent Template</title>

<link rel="stylesheet" href="{{ url_for('static', filename='css/template.css') }}">


</head>
<body>
<header>
<div class="container">
<h1 class="logo">First Web App</h1>
<strong><nav>
<ul class="menu">
<li><a href="{{ url_for('home') }}">Home</a></li>
<li><a href="{{ url_for('about') }}">About</a></li>
</ul>
</nav></strong>
</div>
</header>

{% block content %}
{% endblock %}

</body>
</html>

Moving Forward with Flask and virtualenv


Now that you are familiar with using Flask, you may start using it in your future projects.
One thing to always do is use virtualenv.

Why use virtualenv?

You may use Python for others projects besides web-development.


Your projects might have different versions of Python installed, different dependencies and
packages.

We use virtualenv to create an isolated environment for your Python project. This means that
each project can have its own dependencies regardless of what dependencies every other
project has.

Getting started with virtualenv

First, run this command on your command prompt or terminal:

pip install virtualenv


Second, do the following:

virtualenv “name of virtual environment”


Here you can give a name to the environment. After setting up virtual environment, check
your project folder. It should look like this. The virtual environment needs to be created in the
same directory where your app files are located.

How the directory looks like

Activating the virtual environment

Now go to your terminal or command prompt. Go to the directory that contains the file called
activate. The file called activate is found inside a folder called Scripts for Windows and
bin for OS X and Linux.

For Windows Environment:

name of virtual environment\Scripts\activate


You should see this at beginning of your command prompt line

The next step is to install flask on your virtual environment so that we can run the application
inside our environment. Run the command:

pip install flask


Run your application and go to http://localhost:5000/

We finally made our web application. Now we want to show the whole world our project.
Advanced Features of Flask
Installation¶
.
Test¶

Test file was added since 0.4.6 (thanks to Rdbaker):

$ pip install -r test-requirements.txt


$ cd tests
$ pytest tests.py
How to use¶

In your flask views file (e.g. views/users.py):

from flask import Blueprint


from flask_paginate import Pagination, get_page_parameter

mod = Blueprint('users', __name__)

@mod.route('/')
def index():
search = False
q = request.args.get('q')
if q:
search = True

page = request.args.get(get_page_parameter(), type=int, default=1)

users = User.find(...)
pagination = Pagination(page=page, total=users.count(), search=search,
record_name='users')
# 'page' is the default name of the page parameter, it can be customized
# e.g. Pagination(page_parameter='p', ...)
# or set PAGE_PARAMETER in config file
# also likes page_parameter, you can customize for per_page_parameter
# you can set PER_PAGE_PARAMETER in config file
# e.g. Pagination(per_page_parameter='pp')

return render_template('users/index.html',
users=users,
pagination=pagination,
)

In the users/index.html:

{{ pagination.info }}
{{ pagination.links }}
<table>
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>{{ loop.index + pagination.skip }}</td>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ pagination.links }}

Below are the params for Pagination.__init__(), you can change the settings here.

found: used when searching

page: current page

per_page: how many records displayed on one page

page_parameter: a name(string) of a GET parameter that holds a page index. Use it if you
want to iterate over multiple Pagination objects simultaneously. defautl is ‘page’.

per_page_parameter: a name for per_page likes page_parameter. default is ‘per_page’.

inner_window: how many links arround current page

outer_window: how many links near first/last link

prev_label: text for previous page, default is ‘&laquo;’

next_label: text for next page, default is ‘&raquo;’

search: search or not?

total: total records for pagination

display_msg: text for pagation information


search_msg: text for search information

record_name: record name showed in pagination information

link_size: font size of page links

alignment: the alignment of pagination links

href: Add custom href for links - this supports forms with post method. MUST contain {0} to
format page number

show_single_page: decide whether or not a single page returns pagination

bs_version: the version of bootstrap, default is 2

css_framework: the css framework, default is ‘bootstrap’

anchor: anchor parameter, appends to page href

format_total: number format total, like 1,234, default is False

format_number: number format start and end, like 1,234, default is False

url_coding: coding for url encoding, default is utf-8

bulma_style: page link style for bulma css framework

Flask SQLite
Flask can make use of the SQLite3 module of the python to create the database web
applications. In this section of the tutorial, we will create a CRUD (create - read - update -
delete) application.
CRUD Application in flask
Here, we will manage the employee information in the SQLite database using a flask script to
which the admin can interact. For this purpose, database employee.db contains the related
tables whereas the table Employees contains information about the employees

First, let us create a database employee.DB and the table Employees in SQLite using the
following python script.

EmoloyeeDB.py

import sqlite3

con = sqlite3.connect("employee.db")
print("Database opened successfully")
con.execute("create table Employees (id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL, email TEXT UNIQUE NOT NULL, address TEXT NOT NULL)"
)

print("Table created successfully")

con.close()
Let us look at the view function: index() which is associated with the URL (/). It renders a
template index.html.

@app.route("/")
def index():
return render_template("index.html");
The following HTML template (index.html) is considered as the home page of our
application. It provides the links using which we can add, view, and delete the data stored in
the database.
index.html

<!DOCTYPE html>
<html>
<head>
<title>home</title>
</head>
<body>
<h2>Hi, welcome to the website</h2>
<a href="/add">Add Employee</a><br><br>
<a href ="/view">List Records</a><br><br>
<a href="/delete">Delete Record</a><br><br>
</body>
</html>
The view function add() which is associated with the URL (/add) renders the template
add.html given below. It provides the form to enter the employee information.
add.html

<!DOCTYPE html>
<html>
<head>
<title>Add Employee</title>
</head>
<body>
<h2>Employee Information</h2>
<form action = "/savedetails" method="post">
<table>
<tr><td>Name</td><td><input type="text" name="name"></td></tr>
<tr><td>Email</td><td><input type="email" name="email"></td></tr>
<tr><td>Address</td><td><input type="text" name="address"></td></tr>
<tr><td><input type="submit" value="Submit"></td></tr>
</table>
</form>
</body>
</html>
It also generates the message depending upon the cases in which the data is successfully
inserted, or some error occurred.

@app.route("/savedetails",methods = ["POST","GET"])
def saveDetails():
msg = "msg"
if request.method == "POST":
try:
name = request.form["name"]
email = request.form["email"]
address = request.form["address"]
with sqlite3.connect("employee.db") as con:
cur = con.cursor()
cur.execute("INSERT into Employees (name, email, address) values (?,?,?)",(name,
email,address))
con.commit()
msg = "Employee successfully Added"
except:
con.rollback()
msg = "We can not add the employee to the list"
finally:
return render_template("success.html",msg = msg)
con.close()
It renders a template success.html to display the message to the admin. It also contains a link
to view the records entered by the user.
success.html
<!DOCTYPE html>
<html>
<head>
<title>save details</title>
</head>
<body>
<h3>Hi Admin, {{msg}}</h3>
<a href="/view">View Employees</a>
</body>
</html>
The function delete() is associated to the URL /delete. It renders an HTML template
delete.html which provides the form to the admin that prompts to enter the Employee_Id of
which the records are to be deleted. It also contains a link to the /view URL that shows all the
records to the admin.
The HTML template delete.html is given below.
delete.html

<!DOCTYPE html>
<html>
<head>
<title>delete record</title>
</head>
<body>

<h3>Remove Employee from the list</h3>

<form action="/deleterecord" method="post">


Employee Id <input type="text" name="id">
<input type="submit" value="Submit">
</form>
</body>
</html>
The Employee_Id entered by the admin is posted to the URL /deleterecord which contains the
python code to establish the connection to the database and then delete all the records for the
specified Employee ID. The URL /deleterecord is associated with the function deleterecord()
which is given below.

@app.route("/deleterecord",methods = ["POST"])
def deleterecord():
id = request.form["id"]
with sqlite3.connect("employee.db") as con:
try:
cur = con.cursor()
cur.execute("delete from Employees where id = ?",id)
msg = "record successfully deleted"
except:
msg = "can't be deleted"
finally:
return render_template("delete_record.html",msg = msg)
The function deleterecord() generates a message depending upon the scenario whether the
data is successfully deleted or some error occurred. It renders an HTML template
delete_record.html to show the message to the admin.
delete_record.html
<!DOCTYPE html>
<html>
<head>
<title>delete record</title>
</head>
<body>
<h3>{{msg}}</h3>
<a href="/view">View List</a>
</body>
</html>
The template delete_record.html contains a link to the URL /view which shows the Employee
records to the admin
The template delete_record.html contains a link to the URL /view which shows the Employee
records to the admin.
It is associated with the function view() which establishes the connection to the database,
fetch all the information and pass that information to the HTML template view.html to
display on the client side browser.

app.route("/view")
def view():
con = sqlite3.connect("employee.db")
con.row_factory = sqlite3.Row
cur = con.cursor()
cur.execute("select * from Employees")
rows = cur.fetchall()
return render_template("view.html",rows = rows)
The HTML template view.html which shows all the information on the browser is given
below.
<!DOCTYPE html>
<html>
<head>
<title>List</title>
</head>
<body>

<h3>Employee Information</h3>
<table border=5>
<thead>
<td>ID</td>
<td>Name</td>
<td>Email</td>
<td>Address</td>
</thead>

{% for row in rows %}

<tr>
<td>{{row["id"]}}</td>
<td>{{row["name"]}}</td>
<td>{{row["email"]}}</td>
<td>{{row["address"]}}</td>
</tr>

{% endfor %}
</table>
<br><br>

<a href="/">Go back to home page</a>


</body>
</html>
The full python script is given below.
crud.py
from flask import *
import sqlite3

app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html");

@app.route("/add")
def add():
return render_template("add.html")

@app.route("/savedetails",methods = ["POST","GET"])
def saveDetails():
msg = "msg"
if request.method == "POST":
try:
name = request.form["name"]
email = request.form["email"]
address = request.form["address"]
with sqlite3.connect("employee.db") as con:
cur = con.cursor()
cur.execute("INSERT into Employees (name, email, address) values (?,?,?)",(name,
email,address))
con.commit()
msg = "Employee successfully Added"
except:
con.rollback()
msg = "We can not add the employee to the list"
finally:
return render_template("success.html",msg = msg)
con.close()

@app.route("/view")
def view():
con = sqlite3.connect("employee.db")
con.row_factory = sqlite3.Row
cur = con.cursor()
cur.execute("select * from Employees")
rows = cur.fetchall()
return render_template("view.html",rows = rows)
@app.route("/delete")
def delete():
return render_template("delete.html")

@app.route("/deleterecord",methods = ["POST"])
def deleterecord():
id = request.form["id"]
with sqlite3.connect("employee.db") as con:
try:
cur = con.cursor()
cur.execute("delete from Employees where id = ?",id)
msg = "record successfully deleted"
except:
msg = "can't be deleted"
finally:
return render_template("delete_record.html",msg = msg)

if __name__ == "__main__":
app.run(debug = True)
Run the python script EmployeeDB.py to create the database and the Employees table using
the following command on the terminal.

$ python EmployeeDB.py
Now, run the flask script crud.py and visit https://localhost:5000 on the browser.
View Decorators¶

Python has a really interesting feature called function decorators. This allows some really
neat things for web applications. Because each view in Flask is a function, decorators can be
used to inject additional functionality to one or more functions. The route() decorator is the
one you probably used already. But there are use cases for implementing your own decorator.
For instance, imagine you have a view that should only be used by people that are logged in.
If a user goes to the site and is not logged in, they should be redirected to the login page. This
is a good example of a use case where a decorator is an excellent solution.

Login Required Decorator¶


So let’s implement such a decorator. A decorator is a function that wraps and replaces
another function. Since the original function is replaced, you need to remember to copy the
original function’s information to the new function. Use functools.wraps() to handle this for
you.

This example assumes that the login page is called 'login' and that the current user is stored in
g.user and is None if there is no-one logged in.

from functools import wraps


from flask import g, request, redirect, url_for

def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if g.user is None:
return redirect(url_for('login', next=request.url))
return f(*args, **kwargs)
return decorated_function

To use the decorator, apply it as innermost decorator to a view function. When applying
further decorators, always remember that the route() decorator is the outermost.

@app.route('/secret_page')
@login_required
def secret_page():
pass
Note

The next value will exist in request.args after a GET request for the login page. You’ll have
to pass it along when sending the POST request from the login form. You can do this with a
hidden input tag, then retrieve it from request.form when logging the user in.

<input type="hidden" value="{{ request.args.get('next', '') }}"/>


Caching Decorator¶

Imagine you have a view function that does an expensive calculation and because of that you
would like to cache the generated results for a certain amount of time. A decorator would be
nice for that. We’re assuming you have set up a cache like mentioned in Caching.

Here is an example cache function. It generates the cache key from a specific prefix (actually
a format string) and the current path of the request. Notice that we are using a function that
first creates the decorator that then decorates the function. Sounds awful? Unfortunately it is
a little bit more complex, but the code should still be straightforward to read.

The decorated function will then work as follows

1. get the unique cache key for the current request based on the current path.
2. get the value for that key from the cache. If the cache returned something we will return that
value.
3. otherwise the original function is called and the return value is stored in the cache for the
timeout provided (by default 5 minutes).

Here the code:

from functools import wraps


from flask import request

def cached(timeout=5 * 60, key='view/%s'):


def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
cache_key = key % request.path
rv = cache.get(cache_key)
if rv is not None:
return rv
rv = f(*args, **kwargs)
cache.set(cache_key, rv, timeout=timeout)
return rv
return decorated_function
return decorator

Notice that this assumes an instantiated cache object is available, see Caching for more
information.

Templating Decorator¶

A common pattern invented by the TurboGears guys a while back is a templating decorator.
The idea of that decorator is that you return a dictionary with the values passed to the
template from the view function and the template is automatically rendered. With that, the
following three examples do exactly the same:

@app.route('/')
def index():
return render_template('index.html', value=42)

@app.route('/')
@templated('index.html')
def index():
return dict(value=42)

@app.route('/')
@templated()
def index():
return dict(value=42)
As you can see, if no template name is provided it will use the endpoint of the URL map with
dots converted to slashes + '.html'. Otherwise the provided template name is used. When the
decorated function returns, the dictionary returned is passed to the template rendering
function. If None is returned, an empty dictionary is assumed, if something else than a
dictionary is returned we return it from the function unchanged. That way you can still use
the redirect function or return simple strings.

Here is the code for that decorator:

from functools import wraps


from flask import request, render_template

def templated(template=None):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
template_name = template
if template_name is None:
template_name = request.endpoint \
.replace('.', '/') + '.html'
ctx = f(*args, **kwargs)
if ctx is None:
ctx = {}
elif not isinstance(ctx, dict):
return ctx
return render_template(template_name, **ctx)
return decorated_function
return decorator
Endpoint Decorator¶

When you want to use the werkzeug routing system for more flexibility you need to map the
endpoint as defined in the Rule to a view function. This is possible with this decorator. For
example:

from flask import Flask


from werkzeug.routing import Rule

app = Flask(__name__)
app.url_map.add(Rule('/', endpoint='index'))

@app.endpoint('index')
def my_index():
return "Hello world"

What is a Cookie?

A cookie is just a piece of data which the server sets in the browser. Here is how it works:
1. The browser sends the request for a webpage to the server.
2. The server responds to the browser request by sending the requested webpage along with one
or more cookies.
3. Upon receiving the response, the browser renders the webpage and saves the cookie in the
user computer.
4. The subsequent request to the server will include data from all the cookies in the Cookie
header. This process will continue until the cookie expires. Once the cookie expires, it is
removed from the browser.

Setting a Cookie

In Flask, we use set_cookie() method of the response object to set cookies. The syntax of
set_cookie() method is as follows:

set_cookie(key, value="", max_age=None)


The key is a required argument and refers to the name of the cookie. The value is data you
want to store in the cookie and it defaults to empty string. The max_age refers to the
expiration time of the cookie in seconds, if not set the cookie will cease to exist when the user
closes the browser.

Open main2.py and add the following code just after the contact() view function:

flask_app/main2.py

3from flask import Flask, render_template, request, redirect, url_for, flash, make_response
#...
4@app.route('/cookie/')
def cookie():
5 res = make_response("Setting a cookie")
res.set_cookie('foo', 'bar', max_age=60*60*24*365*2)
6 return res
#...
7

Here we are creating a cookie named foo with the value bar that will last for 2 years.

Start the server and visit http://localhost:5000/cookie/. You should see a page with "Setting a
cookie" as a response. To view the cookie set by the server open Storage Inspector in Firefox
by hitting Shift + F9. A new window will appear at the bottom of the browser window. On
the left side, select "Cookies" storage type and then click on http://localhost:5000/ to view all
cookies set by the server at http://localhost:5000/.

From now onwards, the cookie foo will be sent along with any request to the server at
http://localhost:5000/. We can verify this using the Network Monitor in Firefox. Open
Network Monitor by pressing Ctrl+Shift+E and visit http://localhost:5000/. In the Network
request list on left select the first request and you will get request details on the right pane as
follows:

Note that once the cookie is set the subsequent requests to http://localhost:5000/cookie will
update the expiration time of the cookie.

Accessing Cookies
To access the cookie, we use the cookie attribute of the request object. The cookie attribute is
a dictionary like attribute which contains all the cookies sent by the browser. Open main2.py
and modify the cookie() view function as follows:

flask_app/main2.py

#...
@app.route('/cookie/')
def cookie():
if not request.cookies.get('foo'):
res = make_response("Setting a cookie")
res.set_cookie('foo', 'bar', max_age=60*60*24*365*2)
else:
res = make_response("Value of cookie foo is {}".format(request.cookies.get('foo')))
return res
#...
We have modified our view function to display the cookie value assuming there is a cookie.
Otherwise, it will set a cookie for us.

Visit http://localhost:5000/cookie/ and this time you should get the following response.

The request object is also available inside the template. That means, inside the template, we
can access the cookies using the same way as in Python code. We will see an example of this
in the upcoming section.

Deleting Cookies

To delete a cookie call set_cookie() method with the name of the cookie and any value and
set the max_age argument to 0. Open main2.py file and add the following code just after the
cookie() view function.

flask_app/main2.py

#...
@app.route('/delete-cookie/')
def delete_cookie():
res = make_response("Cookie Removed")
res.set_cookie('foo', 'bar', max_age=0)
return res
#...
Visit http://localhost:5000/delete-cookie/ and you will get the following response:

Now you should have a good understanding of how a cookie works. The following listing
gives you a practical example of how a cookie can be used to store the user preference.

In main2.py add the following code after the delete_cookie() view function.

flask_app/main2.py

#...
@app.route('/article/', methods=['POST', 'GET'])
def article():
if request.method == 'POST':
print(request.form)
res = make_response("")
res.set_cookie("font", request.form.get('font'), 60*60*24*15)
res.headers['location'] = url_for('article')
return res, 302

return render_template('article.html')
#...
Create a new template article.html with the following code:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Article</title>
</head>
<body style="{% if request.cookies.get('font') %}font-family:{{ request.cookies.get('font')
}}{% endif %}">

Select Font Preference: <br>


<form action="" method="post">
<select name="font" onchange="submit()">
<option value="">----</option>
<option value="consolas" {% if request.cookies.get('font') == 'consolas' %}selected{%
endif %}>consolas</option>
<option value="arial" {% if request.cookies.get('font') == 'arial' %}selected{% endif
%}>arial</option>
<option value="verdana" {% if request.cookies.get('font') == 'verdana' %}selected{%
endif %}>verdana</option>
</select>
</form>

<h1>Festus, superbus toruss diligenter tractare de brevis, dexter olla.</h1>

<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam blanditiis debitis
doloribus eos magni minus odit, provident tempora. Expedita fugiat harum in incidunt minus
nam nesciunt voluptate. Facilis nesciunt, similique!
</p>

<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias amet animi aperiam
inventore molestiae quos, reiciendis voluptatem. Ab, cum cupiditate fugit illo incidunt ipsa
neque quam, qui quidem vel voluptatum.</p>

</body>
</html>
The first time user visits http://localhost:5000/article, the page is displayed using the default
browser font. When the user changes the font using the dropdown, we submit the form. The if
condition request.method == 'POST' becomes true and we set a cookie named font with the
value of the selected font that will expire in 15 days, the user is then redirected to
http://localhost:5000/article. And the user is displayed the page in the selected font.

In the browser visit, http://localhost:5000/article and you will be displayed a page in browser
default font.
Select the font from the dropdown and you will be displayed the page in the selected font.

Drawbacks of Cookie

Before using cookies extensively in your project, you must be aware of its shortcomings.

1. Cookies are not secure. The data stored in the cookie is visible to anyone, so you shouldn't
use it to store sensitive data like passwords, credit card details and so on.

2. Cookies can be disabled. Most browsers give users option to disable cookies. When cookies
are disabled you will not get any warnings or error messages, instead, the response header to
set the cookie is simply discarded. To counter these problems, you can Javascript code like
the following to alert the user that your application needs cookies to work properly.

<script>
document.cookie = "foo=bar;";
if (!document.cookie)
{
alert("This website requires cookies to function properly");
}
</script>
3. Each Cookie can store no more than 4KB of data. In addition to that browsers also imposes
limits on the number of cookies a website can set. This limit varies from browser to browser.
Some browsers accept 50 cookies per website and other accepts 30.

4. Cookies are sent every time you request a page from the server. Say you have 20 cookies and
each of them store 4KB of data. That means you have an additional payload of 80KB on
every request!
Sessions
Session is yet another way to store user-specific data between requests. It works similar to
cookies. To use session, you must set the secret key first. The session object of the flask
package is used to set and get session data. The session object works like a dictionary but it
can also keep track modifications.

When we use sessions, the data is stored in the browser as a cookie. The cookie used to store
session data is known session cookie. However, unlike an ordinary cookie, Flask
Cryptographically signs the session cookie. It means that anyone can view the contents of the
cookie, but can't modify the cookie unless he has the secret key used to sign the cookie.
That's why it is recommended to set a long and hard to guess string as a secret key. Once the
session cookie is set, every subsequent request to the server verifies the authenticity of the
cookie by unsinging it using the same secret key. If Flask fails to unsign the cookie then its
content is discarded and a new session cookie is sent to the browser.

How to Read, Write and Delete Session data

The following listing demonstrates how we can read, write and delete session data.
Open main2.py file and add the following code just after the article() view function:

flask_app/main2.py

from flask import Flask, render template, request, redirect, \

url_for, flash, make response, session)

#...
@app.route('/visits-counter/')
def visits():
if 'visits' in session:
session['visits'] = session.get('visits') + 1 # reading and updating session data
else:
session['visits'] = 1 # setting session data
return "Total visits: {}".format(session.get('visits'))

@app.route('/delete-visits/')
def delete_visits():
session.pop('visits', None) # delete visits
return 'Visits deleted'
#...
Notice that we are using session object just like an ordinary dictionary. Start the server if not
already running and visit http://localhost:5000/visits-counter/. You should see total visit
count like this:
Refresh the page several times more to increase the visit count.

Flask sends the session cookie to the client only when you create a new session or modify an
existing session. When you visit http://localhost:5000/visits-counter/ page for the first time,
the body of the else block is executed in the visits() view function and creates a new session.
As we are creating a new session, Flask sends the session cookie to the client. The subsequent
requests to http://localhost:5000/visits-counter/ execute the code in the if block where are
updating the value of visits counter in the session. Modifying a session means that a new
cookie needs to be created that's why Flask again sends the new session cookie to the client.

To delete the session data visit http://localhost:5000/delete-visits/.

If you now visit http://localhost:5000/visits-counter/, the visit counter will again start from 1.
By default, session cookie lasts until the browser is closed. To prolong the life of the session
cookie set permanent attribute of the session object to True. When permanent is set
to True the session cookie will last for permanent_session_lifetime.
The permanent_session_lifetime is a datetime.timedelta attribute of Flask object, its default
value is 31 days. We can change that by specifying a new value
to permanent_session_lifetime attribute or by
setting PERMANENT_SESSION_LIFETIME configuration key.

import datetime

app = Flask(__name__)
app.permanent_session_lifetime = datetime.timedelta(days=365)
# app.config['PERMANENT_SESSION_LIFETIME'] = datetime.timedelta(days=365) # you
can also do this
Just like the request object, the session object is also available in the templates.

Modifying Session Data

Note: Before following along delete all the cookies set by the localhost.

Most of the time session object automatically picks up modifications on it. However, there
are some occasions, like modifications on mutable data structures are not picked up
automatically. For such cases, you have to set modified attribute of the session object to True.
If you don't set modified attribute to True Flask will not send the updated session cookie to
the client. The following listing demonstrates how to use modified attribute of
the session object. Open main2.py file and add the following code just before
the delete_visits() view function.

flask_app/main2.py

#...
@app.route('/session/')
def updating_session():
res = str(session.items())

cart_item = {'pineapples': '10', 'apples': '20', 'mangoes': '30'}


if 'cart_item' in session:
session['cart_item']['pineapples'] = '100'
session.modified = True
else:
session['cart_item'] = cart_item

return res
#...
The first time you visit http://localhost:5000/session/ the code in the else block is executed
and creates a new session where session data is a dictionary. The subsequent request
to http://localhost:5000/session/ updates the session data by setting pineapples count to 100.
In the next line, we are setting modified attribute to True because without it Flask will not
send the updated session cookie to the client.
Start the server if not already running and visit http://localhost:5000/session/. You will be
displayed an empty session dictionary because browser had no session cookie to send to the
server:

Reload the page again and you will be displayed session dictionary with 10 pineapples as
follows:

Reload the page for the third time and you will see session dictionary with 100 pineapples
instead of 10 as follows:

The session object has picked up this modification because of the modified attribute. We can
verify this by deleting the session cookie and commenting out the line which sets
the modified attribute to True. Now after the first request you will always be displayed
session dictionary with 10 pineapples.

This completes all you need to know about sessions in Flask. And don't forget by default
sessions in Flask are client-side sessions.

Applications fail, servers fail. Sooner or later you will see an exception in production. Even if
your code is 100% correct, you will still see exceptions from time to time. Why? Because
everything else involved will fail. Here are some situations where perfectly fine code can lead
to server errors:
• the client terminated the request early and the application was still reading from the incoming
data
• the database server was overloaded and could not handle the query
• a filesystem is full
• a harddrive crashed
• a backend server overloaded
• a programming error in a library you are using
• network connection of the server to another system failed

And that’s just a small sample of issues you could be facing. So how do we deal with that sort
of problem? By default if your application runs in production mode, Flask will display a very
simple page for you and log the exception to the logger.

But there is more you can do, and we will cover some better setups to deal with errors.

Error Logging Tools¶

Sending error mails, even if just for critical ones, can become overwhelming if enough users
are hitting the error and log files are typically never looked at. This is why we recommend
using Sentry for dealing with application errors. It’s available as an Open Source project on
GitHub and is also available as a hosted version which you can try for free. Sentry aggregates
duplicate errors, captures the full stack trace and local variables for debugging, and sends you
mails based on new errors or frequency thresholds.

To use Sentry you need to install the sentry-sdk client with extra flask dependencies:

$ pip install sentry-sdk[flask]

And then add this to your Flask app:

import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration

sentry_sdk.init('YOUR_DSN_HERE',integrations=[FlaskIntegration()])

The YOUR_DSN_HERE value needs to be replaced with the DSN value you get from your
Sentry installation.

After installation, failures leading to an Internal Server Error are automatically reported to
Sentry and from there you can receive error notifications.

Follow-up reads:

• Sentry also supports catching errors from your worker queue (RQ, Celery) in a similar fashion.
See the Python SDK docs for more information.
• Getting started with Sentry
• Flask-specific documentation.
Error handlers¶

You might want to show custom error pages to the user when an error occurs. This can be
done by registering error handlers.

An error handler is a normal view function that returns a response, but instead of being
registered for a route, it is registered for an exception or HTTP status code that would be
raised while trying to handle a request.

Registering¶

Register handlers by decorating a function with errorhandler(). Or use


register_error_handler() to register the function later. Remember to set the error code when
returning the response.

@app.errorhandler(werkzeug.exceptions.BadRequest)
def handle_bad_request(e):
return 'bad request!', 400

# or, without the decorator


app.register_error_handler(400, handle_bad_request)

werkzeug.exceptions.HTTPException subclasses like BadRequest and their HTTP codes


are interchangeable when registering handlers. (BadRequest.code == 400)

Non-standard HTTP codes cannot be registered by code because they are not known by
Werkzeug. Instead, define a subclass of HTTPException with the appropriate code and
register and raise that exception class.

class InsufficientStorage(werkzeug.exceptions.HTTPException):
code = 507
description = 'Not enough storage space.'

app.register_error_handler(InsufficientStorage, handle_507)

raise InsufficientStorage()

Handlers can be registered for any exception class, not just HTTPException subclasses or
HTTP status codes. Handlers can be registered for a specific class, or for all subclasses of a
parent class.

Handling¶

When an exception is caught by Flask while handling a request, it is first looked up by code.
If no handler is registered for the code, it is looked up by its class hierarchy; the most specific
handler is chosen. If no handler is registered, HTTPException subclasses show a generic
message about their code, while other exceptions are converted to a generic 500 Internal
Server Error.
For example, if an instance of ConnectionRefusedError is raised, and a handler is registered
for ConnectionError and ConnectionRefusedError, the more specific
ConnectionRefusedError handler is called with the exception instance to generate the
response.

Handlers registered on the blueprint take precedence over those registered globally on the
application, assuming a blueprint is handling the request that raises the exception. However,
the blueprint cannot handle 404 routing errors because the 404 occurs at the routing level
before the blueprint can be determined.

Generic Exception Handlers¶

It is possible to register error handlers for very generic base classes such as HTTPException
or even Exception. However, be aware that these will catch more than you might expect.

An error handler for HTTPException might be useful for turning the default HTML errors
pages into JSON, for example. However, this handler will trigger for things you don’t cause
directly, such as 404 and 405 errors during routing. Be sure to craft your handler carefully so
you don’t lose information about the HTTP error.

from flask import json


from werkzeug.exceptions import HTTPException

@app.errorhandler(HTTPException)
def handle_exception(e):
"""Return JSON instead of HTML for HTTP errors."""
# start with the correct headers and status code from the error
response = e.get_response()
# replace the body with JSON
response.data = json.dumps({
"code": e.code,
"name": e.name,
"description": e.description,
})
response.content_type = "application/json"
return response

An error handler for Exception might seem useful for changing how all errors, even
unhandled ones, are presented to the user. However, this is similar to doing except Exception:
in Python, it will capture all otherwise unhandled errors, including all HTTP status codes. In
most cases it will be safer to register handlers for more specific exceptions. Since
HTTPException instances are valid WSGI responses, you could also pass them through
directly.

from werkzeug.exceptions import HTTPException

@app.errorhandler(Exception)
def handle_exception(e):
# pass through HTTP errors
if isinstance(e, HTTPException):
return e

# now you're handling non-HTTP exceptions only


return render_template("500_generic.html", e=e), 500

Error handlers still respect the exception class hierarchy. If you register handlers for both
HTTPException and Exception, the Exception handler will not handle HTTPException
subclasses because it the HTTPException handler is more specific.

Unhandled Exceptions¶

When there is no error handler registered for an exception, a 500 Internal Server Error will be
returned instead. See flask.Flask.handle_exception() for information about this behavior.

If there is an error handler registered for InternalServerError, this will be invoked. As of


Flask 1.1.0, this error handler will always be passed an instance of InternalServerError, not
the original unhandled error. The original error is available as e.original_exception. Until
Werkzeug 1.0.0, this attribute will only exist during unhandled errors, use getattr to get
access it for compatibility.

@app.errorhandler(InternalServerError)
def handle_500(e):
original = getattr(e, "original_exception", None)

if original is None:
# direct 500 error, such as abort(500)
return render_template("500.html"), 500

# wrapped unhandled error


return render_template("500_unhandled.html", e=original), 500
Logging¶

See Logging for information on how to log exceptions, such as by emailing them to admins.

Debugging Application Errors¶

For production applications, configure your application with logging and notifications as
described in Application Errors. This section provides pointers when debugging deployment
configuration and digging deeper with a full-featured Python debugger.

When in Doubt, Run Manually¶

Having problems getting your application configured for production? If you have shell access
to your host, verify that you can run your application manually from the shell in the
deployment environment. Be sure to run under the same user account as the configured
deployment to troubleshoot permission issues. You can use Flask’s builtin development
server with debug=True on your production host, which is helpful in catching configuration
issues, but be sure to do this temporarily in a controlled environment. Do not run in
production with debug=True.

Working with Debuggers¶

To dig deeper, possibly to trace code execution, Flask provides a debugger out of the box (see
Debug Mode). If you would like to use another Python debugger, note that debuggers
interfere with each other. You have to set some options in order to use your favorite
debugger:

• debug - whether to enable debug mode and catch exceptions


• use_debugger - whether to use the internal Flask debugger
• use_reloader - whether to reload and fork the process if modules were changed

debug must be True (i.e., exceptions must be caught) in order for the other two options to
have any value.

If you’re using Aptana/Eclipse for debugging you’ll need to set both use_debugger and
use_reloader to False.

A possible useful pattern for configuration is to set the following in your config.yaml (change
the block as appropriate for your application, of course):

FLASK:
DEBUG: True
DEBUG_WITH_APTANA: True

Then in your application’s entry-point (main.py), you could have something like:

if __name__ == "__main__":
# To allow aptana to receive errors, set use_debugger=False
app = create_app(config="config.yaml")

use_debugger = app.debug and not(app.config.get('DEBUG_WITH_APTANA'))


app.run(use_debugger=use_debugger, debug=app.debug,
use_reloader=use_debugger, host='0.0.0.0')
Message Flashing¶

Good applications and user interfaces are all about feedback. If the user does not get enough
feedback they will probably end up hating the application. Flask provides a really simple way
to give feedback to a user with the flashing system. The flashing system basically makes it
possible to record a message at the end of a request and access it next request and only next
request. This is usually combined with a layout template that does this. Note that browsers
and sometimes web servers enforce a limit on cookie sizes. This means that flashing
messages that are too large for session cookies causes message flashing to fail silently.

Simple Flashing¶
So here is a full example:

from flask import Flask, flash, redirect, render_template, \


request, url_for

app = Flask(__name__)
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'

@app.route('/')
def index():
return render_template('index.html')

@app.route('/login', methods=['GET', 'POST'])


def login():
error = None
if request.method == 'POST':
if request.form['username'] != 'admin' or \
request.form['password'] != 'secret':
error = 'Invalid credentials'
else:
flash('You were successfully logged in')
return redirect(url_for('index'))
return render_template('login.html', error=error)

And here is the layout.html template which does the magic:

<!doctype html>
<title>My Application</title>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block body %}{% endblock %}

Here is the index.html template which inherits from layout.html:

{% extends "layout.html" %}
{% block body %}
<h1>Overview</h1>
<p>Do you want to <a href="{{ url_for('login') }}">log in?</a>
{% endblock %}

And here is the login.html template which also inherits from layout.html:

{% extends "layout.html" %}
{% block body %}
<h1>Login</h1>
{% if error %}
<p class=error><strong>Error:</strong> {{ error }}
{% endif %}
<form method=post>
<dl>
<dt>Username:
<dd><input type=text name=username value="{{
request.form.username }}">
<dt>Password:
<dd><input type=password name=password>
</dl>
<p><input type=submit value=Login>
</form>
{% endblock %}
Flashing With Categories¶
Changelog

New in version 0.3.

It is also possible to provide categories when flashing a message. The default category if
nothing is provided is 'message'. Alternative categories can be used to give the user better
feedback. For example error messages could be displayed with a red background.

To flash a message with a different category, just use the second argument to the flash()
function:

flash(u'Invalid password provided', 'error')

Inside the template you then have to tell the get_flashed_messages() function to also return
the categories. The loop looks slightly different in that situation then:

{% with messages = get_flashed_messages(with_categories=true) %}


{% if messages %}
<ul class=flashes>
{% for category, message in messages %}
<li class="{{ category }}">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}

This is just one example of how to render these flashed messages. One might also use the
category to add a prefix such as <strong>Error:</strong> to the message.

Filtering Flash Messages¶


Changelog
New in version 0.9.

Optionally you can pass a list of categories which filters the results of
get_flashed_messages(). This is useful if you wish to render each category in a separate
block.

{% with errors = get_flashed_messages(category_filter=["error"]) %}


{% if errors %}
<div class="alert-message block-message error">
<a class="close" href="#">×</a>
<ul>
{%- for msg in errors %}
<li>{{ msg }}</li>
{% endfor -%}
</ul>
</div>
{% endif %}
{% endwith %}

The Flask-Mail extension provides a simple interface to set up SMTP with your Flask
application and to send messages from your views and scripts.

Links¶

• documentation
• source
• changelog

Installing Flask-Mail¶

Install with pip and easy install:

pip install Flask-Mail

or download the latest version from version control:

git clone https://github.com/mattupstate/flask-mail.git


cd flask-mail
python setup.py install

If you are using virtualenv, it is assumed that you are installing flask-mail in the same
virtualenv as your Flask application(s).

Configuring Flask-Mail¶
Flask-Mail is configured through the standard Flask config API. These are the available
options (each is explained later in the documentation):

• MAIL_SERVER : default ‘localhost’


• MAIL_PORT : default 25
• MAIL_USE_TLS : default False
• MAIL_USE_SSL : default False
• MAIL_DEBUG : default app.debug
• MAIL_USERNAME : default None
• MAIL_PASSWORD : default None
• MAIL_DEFAULT_SENDER : default None
• MAIL_MAX_EMAILS : default None
• MAIL_SUPPRESS_SEND : default app.testing
• MAIL_ASCII_ATTACHMENTS : default False

In addition the standard Flask TESTING configuration option is used by Flask-Mail in unit
tests (see below).

Emails are managed through a Mail instance:

from flask import Flask


from flask_mail import Mail

app = Flask(__name__)
mail = Mail(app)

In this case all emails are sent using the configuration values of the application that was
passed to the Mail class constructor.

Alternatively you can set up your Mail instance later at configuration time, using the
init_app method:

mail = Mail()

app = Flask(__name__)
mail.init_app(app)

In this case emails will be sent using the configuration values from Flask’s current_app
context global. This is useful if you have multiple applications running in the same process
but with different configuration options.

Sending messages¶

To send a message first create a Message instance:


from flask_mail import Message

@app.route("/")
def index():

msg = Message("Hello",
sender="from@example.com",
recipients=["to@example.com"])

You can set the recipient emails immediately, or individually:

msg.recipients = ["you@example.com"]
msg.add_recipient("somebodyelse@example.com")

If you have set MAIL_DEFAULT_SENDER you don’t need to set the message sender
explicity, as it will use this configuration value by default:

msg = Message("Hello",
recipients=["to@example.com"])

If the sender is a two-element tuple, this will be split into name and address:

msg = Message("Hello",
sender=("Me", "me@example.com"))

assert msg.sender == "Me <me@example.com>"

The message can contain a body and/or HTML:

msg.body = "testing"
msg.html = "<b>testing</b>"

Finally, to send the message, you use the Mail instance configured with your Flask
application:

mail.send(msg)

Bulk emails¶

Usually in a web application you will be sending one or two emails per request. In certain
situations you might want to be able to send perhaps dozens or hundreds of emails in a single
batch - probably in an external process such as a command-line script or cronjob.

In that case you do things slightly differently:

with mail.connect() as conn:


for user in users:
message = '...'
subject = "hello, %s" % user.name
msg = Message(recipients=[user.email],
body=message,
subject=subject)

conn.send(msg)

The connection to your email host is kept alive and closed automatically once all the
messages have been sent.

Some mail servers set a limit on the number of emails sent in a single connection. You can
set the max amount of emails to send before reconnecting by specifying the
MAIL_MAX_EMAILS setting.

Attachments¶

Adding attachments is straightforward:

with app.open_resource("image.png") as fp:


msg.attach("image.png", "image/png", fp.read())

See the API for details.

If MAIL_ASCII_ATTACHMENTS is set to True, filenames will be converted to an ASCII


equivalent. This can be useful when using a mail relay that modify mail content and mess up
Content-Disposition specification when filenames are UTF-8 encoded. The conversion to
ASCII is a basic removal of non-ASCII characters. It should be fine for any unicode character
that can be decomposed by NFKD into one or more ASCII characters. If you need
romanization/transliteration (i.e ß → ss) then your application should do it and pass a proper
ASCII string.

Unit tests and suppressing emails¶

When you are sending messages inside of unit tests, or in a development environment, it’s
useful to be able to suppress email sending.

If the setting TESTING is set to True, emails will be suppressed. Calling send() on your
messages will not result in any messages being actually sent.

Alternatively outside a testing environment you can set MAIL_SUPPRESS_SEND to False.


This will have the same effect.

However, it’s still useful to keep track of emails that would have been sent when you are
writing unit tests.
In order to keep track of dispatched emails, use the record_messages method:

with mail.record_messages() as outbox:

mail.send_message(subject='testing',
body='test',
recipients=emails)

assert len(outbox) == 1
assert outbox[0].subject == "testing"

The outbox is a list of Message instances sent.

The blinker package must be installed for this method to work.

Note that the older way of doing things, appending the outbox to the g object, is now
deprecated.

Header injection¶

To prevent header injection attempts to send a message with newlines in the subject, sender
or recipient addresses will result in a BadHeaderError.

Signalling support¶

New in version 0.4.

Flask-Mail now provides signalling support through a email_dispatched signal. This is sent
whenever an email is dispatched (even if the email is not actually sent, i.e. in a testing
environment).

A function connecting to the email_dispatched signal takes a Message instance as a first


argument, and the Flask app instance as an optional argument:

def log_message(message, app):


app.logger.debug(message.subject)

email_dispatched.connect(log_message)

API¶
class flask_mail.Mail(app=None)¶
Manages email messaging

Parameters: app – Flask instance


send(message)¶
Sends a single message instance. If TESTING is True the message will not actually be
sent.

Parameters: message – a Message instance.

connect()¶
Opens a connection to the mail host.

send_message(*args, **kwargs)¶
Shortcut for send(msg).

Takes same arguments as Message constructor.

Versionadded : 0.3.5
class flask_mail.Attachment(filename=None, content_type=None, data=None,
disposition=None, headers=None)¶
Encapsulates file attachment information.

Versionadded : 0.3.5

• filename – filename of attachment


• content_type – file mimetype
Parameters:
• data – the raw file data
• disposition – content-disposition (if any)

class flask_mail.Connection(mail)¶
Handles connection to host.

send(message, envelope_from=None)¶
Verifies and sends message.

• message – Message instance.


Parameters: • envelope_from – Email address to be used in MAIL FROM
command.

send_message(*args, **kwargs)¶
Shortcut for send(msg).

Takes same arguments as Message constructor.

Versionadded : 0.3.5
class flask_mail.Message(subject='', recipients=None, body=None, html=None,
sender=None, cc=None, bcc=None, attachments=None, reply_to=None, date=None,
charset=None, extra_headers=None, mail_options=None, rcpt_options=None)¶
Encapsulates an email message.

Parameters:

• subject – email subject header


• recipients – list of email addresses
• body – plain text message
• html – HTML message
• sender – email sender address, or MAIL_DEFAULT_SENDER by default
• cc – CC list
• bcc – BCC list
• attachments – list of Attachment instances
• reply_to – reply-to address
• date – send date
• charset – message character set
• extra_headers – A dictionary of additional headers for the message
• mail_options – A list of ESMTP options to be used in MAIL FROM command
• rcpt_options – A list of ESMTP options to be used in RCPT commands

attach(filename=None, content_type=None, data=None, disposition=None,


headers=None)¶
Adds an attachment to the message.

Parameters:

• filename – filename of attachment


• content_type – file mimetype
• data – the raw file data
• disposition – content-disposition (if any)

add_recipient(recipient)¶
Adds another recipient to the message.

Parameters:
recipient – email address of recipient.
Deploy to Production¶

This part of the tutorial assumes you have a server that you want to deploy your application
to. It gives an overview of how to create the distribution file and install it, but won’t go into
specifics about what server or software to use. You can set up a new environment on your
development computer to try out the instructions below, but probably shouldn’t use it for
hosting a real public application. See Deployment Options for a list of many different ways to
host your application.

Build and Install¶

When you want to deploy your application elsewhere, you build a distribution file. The
current standard for Python distribution is the wheel format, with the .whl extension. Make
sure the wheel library is installed first:

$ pip install wheel

Running setup.py with Python gives you a command line tool to issue build-related
commands. The bdist_wheel command will build a wheel distribution file.

$ python setup.py bdist_wheel

You can find the file in dist/flaskr-1.0.0-py3-none-any.whl. The file name is the name of the
project, the version, and some tags about the file can install.

Copy this file to another machine, set up a new virtualenv, then install the file with pip.

$ pip install flaskr-1.0.0-py3-none-any.whl

Pip will install your project along with its dependencies.

Since this is a different machine, you need to run init-db again to create the database in the
instance folder.

$ export FLASK_APP=flaskr
$ flask init-db

When Flask detects that it’s installed (not in editable mode), it uses a different directory for
the instance folder. You can find it at venv/var/flaskr-instance instead.

Configure the Secret Key¶

In the beginning of the tutorial that you gave a default value for SECRET_KEY. This should
be changed to some random bytes in production. Otherwise, attackers could use the public
'dev' key to modify the session cookie, or anything else that uses the secret key.

You can use the following command to output a random secret key:
$ python -c 'import os; print(os.urandom(16))'

b'_5#y2L"F4Q8z\n\xec]/'

Create the config.py file in the instance folder, which the factory will read from if it exists.
Copy the generated value into it.

venv/var/flaskr-instance/config.py¶
SECRET_KEY = b'_5#y2L"F4Q8z\n\xec]/'

You can also set any other necessary configuration here, although SECRET_KEY is the only
one needed for Flaskr.

Run with a Production Server¶

When running publicly rather than in development, you should not use the built-in
development server (flask run). The development server is provided by Werkzeug for
convenience, but is not designed to be particularly efficient, stable, or secure.

Instead, use a production WSGI server. For example, to use Waitress, first install it in the
virtual environment:

$ pip install waitress

You need to tell Waitress about your application, but it doesn’t use FLASK_APP like flask
run does. You need to tell it to import and call the application factory to get an application
object.

$ waitress-serve --call 'flaskr:create_app'

Serving on http://0.0.0.0:8080

See Deployment Options for a list of many different ways to host your application. Waitress
is just an example, chosen for the tutorial because it supports both Windows and Linux.
There are many more WSGI servers and deployment options that you may choose for your
project.

You might also like