Python and Flask - Notes
Python and Flask - Notes
Python
In this class, Python 3.6 will be used. For those unfamiliar, Python is an interpreted language that will
be used in the context of this class to generate dynamic websites and web applications.
Some basic Python syntax:
o Print a string to the screen:
o print("Hello, world!")
o Print a format string (variable names enclosed with {} will be replaced by variable values)
o print(f"Hello, {name}!")
o Set variable name to the user input returned by input()
o name = input()
o Conditional statement:
o if x > 0:
o print("x is positive")
o elif x < 0:
o print("x is negative")
o else:
o print("x is zero")
elif and else blocks are optional.
Note that indentation in Python is not stylistic, but rather is used to demarcate blocks of
code. In this example, the Python interpreter knows where the conditional if block ends and the elif block
begins because of the changes in indentation.
Data Types
int : integer value
float : floating point value
str : text string
bool : boolean value (True or False)
None : empty value
Note that Python is a weakly typed language.
Sequences
Strings:
name = "Alice"
print(name[0])
o Strings are justs sequence of characters, and can be indexed as such.
Tuples:
coordinates = (10.0, 20.0)
print(coordinates[1])
o Tuples are immutable collections of values under a single name, which can be indexed
positionally.
Lists:
names = ["Alice", "Bob", "Charlie"]
print(names[2])
o Lists are mutable collections of values under a single name, which can be indexed positionally.
o Indexing out of range raises a Python ‘exception’. In this case, an IndexError, because there is
no fourth value in names for Python to return.
Note that any sequence in Python can contain any number of data types.
Sets:
s = set()
s.add(1)
s.add(3)
s.add(5)
o Sets are unordered collection of unique items. Because they are unordered, they cannot be
indexed.
o s is
a set, an unordered collection of unique items
Dictionaries:
ages = {"Alice": 22, "Bob": 27}
print(ages["Alice"])
ages["Alice"] += 1
o Dictionaries (or dicts) are like lists, except that they are unordered and their values are indexed
by keys.
o The += operator increments the left-hand side by the right-hand side.
Loops
for i in range(5):
print(i)
For-loops iterate over their bodies a limited number of times. In this case, the number of iterations is set
by range(5).
range(5) returns the sequence of numbers starting at 0 through 4. Each value is passed to i once,
resulting in the loop running a total of 5 times. i is normally referred to as an iterator variable.
for name in names:
print(name)
This for-loop iterates over names, which is a list. Every value in the list is assigned, in order, to the
iterator name once.
Functions
Python has built-in functions, such as print() and input(), but Python also allows for the creation of
user-defined functions
def square(x):
return x * x
o This is a function called square, which takes a single argument x, and returns the value x * x.
o Like loops, the body of a function must be indented.
o for i in range(10):
o print("{} squared is {}".format(i, square(i)))
This loop, which prints out the results of square with a range of arguments, using an
older method for format strings.
Trying to call a function that hasn’t been defined will raise a NameError exception.
Modules
Modules are separate .py files of code, often written by others, used in a new file without rewriting all
the old code again. Using modules allows, for example, the use of functions across a program larger than a
single file.
Assuming the square function in the earlier example was saved in functions.py, adding this line atop a
new module will allow for the use of square there as well.
from functions import square
If, for example, functions.py also included the example loop demonstration of the square function, that
loop would be executed every time square was imported from functions, because the Python interpreter reads
through the entire functions.py file. To remedy this, code that should only run when their containing file is run
directly should be encapsulated in a function, called, for example, main. After, the following should be
appended:
if __name__ == "__main__":
main()
This should be interpreted as saying ‘if this file is currently being run’, execute main.
Classes
A Python class can be thought of as a way to define a new, custom Python data type, somewhat
analagous to defining a custom function.
This creates a new class called Point:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
o The __init__ function is a special function that defines the information needed when a
new Point is created. self is always required, which refers to the Point being created, while x and y are its
coordinates.
o self.x and self.y actually do the work of creating x and y attributes for the Point and assigning
the m the values passed to __init__.
o By convention, class names tend to start with a capital letter.
This instantiates a new Point with x = 3 and y = 5:
p = Point(3, 5)
o When this line is run, the __init__ function of the Point class is automatically run.
To access the x attribute of p, use dot notation:
print(p.x)
Flask
HTTP (Hypertext Transfer Protocol) is the system the internet uses to interact and communicate
between computers and servers. When a URL is entered into a browser, an HTTP request is sent to a server,
which interprets the request and sends appropriate HTTP response, which, if all goes as expected, contains the
requested information to be displayed by the web browser.
Having already begun to design websites, the next step is to write the code that takes care of the server-
side processing: receiving and interpreting requests, and generating a response for the user.
Flask a microframework written in Python that makes it easy to get a simple web application up and
running with some features that can be useful in the development process.
A Simple App
Flask code is generally stored inside application.py, and might look like so:
from flask import Flask # Import the class `Flask` from the `flask` module, written by
someone else.
app = Flask(__name__) # Instantiate a new web application called `app`, with `__name__`
representing the current file
@app.route("/") # A decorator; when the user goes to the route `/`, exceute the function
immediately below
def index():
return "Hello, world!"
o Flask is designed in terms of routes. A route is the part of the URL that determines which page is
being requested. The route for the default page is simply /.
To start up a flask application, run flask run in the directory where application.py is located,
with flask being the web server. Flask will print out the URL the server is running on and where the website
can be accessed at.
o flask run produces an error, try running export FLASK_APP=application.py to make sure it
knows to look for application.py as the web server.
Fancier Flask and Jinja2
@app.route("/<string:name>")
def hello(name):
return f"Hello, {name}!"
When any string is entered as a route, that will be stored as name, which is can then be used inside the
decorated function.
Since Python code is rendering the website, anything Python is capable of can be used. For
example, name can be capitalized before it’s displayed:
name = name.capitalize()
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html")
In index.html:
<h1>{{ headline }}</h1>
Loops:
{% for name in names %}
<li>{{ name }}</li>
{% endfor %}
names should be something that can be looped over, like a Python list, for example.
If there are multiple routes on the Flask server, then one route can link to another as so:
<a href="{{ url_for('more') }}">See more...</a>
@app.route("/hello", methods=["POST"])
def hello():
name = request.form.get("name") # take the request the user made, access the form,
# and store the field called `name` in a Python variable also
called `name`
return render_template("hello.html", name=name)
The route /hello is the same hello listed in the Jinja2 code. This route can also accept the POST method,
which is how the form’s data is being submitted. If any other method is used to access this route, a Method Not
Allowed error will be raised.
o If there are multiple request methods that should be allowed, which method is being used can be
checked with request.method, which will be equal to, for example, "GET" or "POST".
Sessions
Sessions are how Flask can keep track of data that pertains to a particular user. Let’s take a note-taking
app, for example. Users should only be able to see their own notes.
To use sessions, they must be imported and set up:
from flask import Flask, render_template, request, session # gives access to a variable called
`session`
# which can be used to keep vaules
that are specific to a particular user
from flask_session import Session # an additional extension to sessions which allows them
# to be stored server-side
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
Then, assuming there is some HTML form that can submit a note, the note can be stored in a place
specific to the user using their session:
@app.route("/", methods=["GET", "POST"])
def index():
if session.get("notes") is None:
session["notes"] = []
if request.method == "POST":
note = request.form.get("note")
session["notes"].append(note)
notes is the list where the notes will be stored. If the user doesn’t have a notes list already (checked
with if session.get("notes") is None), then they are given an empty one.
If a request is submitted via "POST" (that is, through the form), then the note is processed from the form
in the same way as before.
The processed note, now in a Python variable called note, is appended to the notes list. This list is itself
inside a dict called session. Every user has a unique session dict, and therefore a unique notes list.
Finally, the notelist is rendered by passing session["notes"] to render_template.