Categories
Flask

Python Web Development with Flask — Errors, Sessions, and JSON

Flask is a simple web framework written in Python.

In this article, we’ll look at how to develop simple Python web apps with Flask.

Redirects and Errors

We can redirect to another endpoint in our Flask app.

To do that, we write:

from flask import Flask, abort, redirect, url_for
app = Flask(__name__)

@app.route('/')
def index():
    return redirect(url_for('login'))

@app.route('/login')
def login():
    abort(401)

When we go to / , then we’re redirected to the /login route.

Then we get the 401 response because we called abort with the response.

We can create a 404 page by writing:

app.py

from flask import Flask, render_template
app = Flask(__name__)

@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404

templates/page_not_found.html

<p>not found</p>

Now when we go to any URL, we render the page_not_found.html template with a 404 response status code.

Response Headers

We can return headers with our response by using the make_response function to create the response.

For example, we can write:

from flask import Flask, make_response, render_template
app = Flask(__name__)

@app.errorhandler(404)
def page_not_found(error):
    resp = make_response(render_template('page_not_found.html'), 404)
    resp.headers['X-Something'] = 'A value'
    return resp

We have our 404 route.

In it, we create the response with the make_response function.

Then we pass in the template into function as the first argument.

The 2nd argument is the status code.

resp.headers is a dictionary with the headers.

Finally, we return the response object.

APIs with JSON

We can return JSON s our response.

To do that, all we have to do is return the dictionary for our JSON.

For example, we can write:

from flask import Flask
app = Flask(__name__)

@app.route("/me")
def me_api():
    return {
        "first_name": 'james',
        "last_name": 'smith'
    }

to return a dictionary in our route function.

It’ll be rendered as JSON automatically.

We can also use the jsonify function if we have anything other than a dictionary that we want to render into JSON:

from flask import Flask, jsonify
app = Flask(__name__)

@app.route("/me")
def me_api():
    users = [
        {
            'first_name': 'jane',
            'last_name': 'smith',
        },
        {
            'first_name': 'mary',
            'last_name': 'wong',
        },
    ]
    return jsonify(users)

Sessions

Flask can handle sessions automatically.

We can use the session object from the Flask module to store sessions.

For example, we can write:

from flask import Flask, session, request, redirect, url_for
from markupsafe import escape

app = Flask(__name__)
app.secret_key = b'secret'

@app.route('/')
def index():
    if 'username' in session:
        return 'Logged in as %s' % escape(session['username'])
    return 'You are not logged in'

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''
        <form method="post">
            <p><input type=text name=username>
            <p><input type=submit value=Login>
        </form>
    '''

@app.route('/logout')
def logout():
    session.pop('username', None)
    return redirect(url_for('index'))

We set the secret_key property to set the secret key.

In the index route function, we get the username value from the session object.

It’s a dictionary so we get the value by the key.

The login route function takes the username value from the form data if we’re making a POST request.

Then we redirect to index once that’s done.

If it’s a GET request, then we render the login form.

In the logout route function, we remove the value with the keyusername by setting it to None .

And then we redirect back to index .

Conclusion

We can do redirects, show error pages, store sessions, and return JSON easily with Flask.

Categories
Flask

Python Web Development with Flask — Request and Response

Flask is a simple web framework written in Python.

In this article, we’ll look at how to develop simple Python web apps with Flask.

The Request Object

We can get data from the request object.

To get form data, we can write:

from flask import Flask, request
app = Flask(__name__)

@app.route('/login', methods=['POST', 'GET'])
def login():
    if request.method == 'POST':
        if 'username' in request.form and 'password' in request.form:
            return '%s:%s' % (
                request.form['username'],
                request.form['password']
            )
        else:
            return 'Invalid username/password'

We check if 'username' and 'password' keys are in request.form .

request.form has the form data key-value pairs.

If they’re both present when we make the POST request to http://127.0.0.1:5000/login, then we return the username and password combined as the response.

Otherwise, we return ‘Invalid username/password’ .

Alternatively, we can write:

from flask import Flask, request
app = Flask(__name__)

@app.route('/login', methods=['POST', 'GET'])
def login():
    if request.method == 'POST':
        username = request.args.get('username', '')
        password = request.args.get('password', '')
        if username != '' and password != '':
            return '%s:%s' % (
                username,
                password
            )
        else:
            return 'Invalid username/password'

We call request.args.get to get the value with the given form data key.

The 2nd argument is the default value.

So we can check username and password against an empty string instead to see if they have a value or not.

File Uploads

We can accept file uploads with Flask.

For example, we can write:

from flask import Flask, request
from werkzeug.utils import secure_filename
app = Flask(__name__)

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('./uploads/%s' % (secure_filename(f.filename)))
        return 'file uploaded'

to add the upload route.

We check the upload_file function for the route.

Then we check if the method of the request is 'POST' .

If it is, then we get the file from request.files .

Then we save the file with f.save and the path to save to.

secure_filename creates an escaped file name.

f.filename has the file name of the file that’s sent with the request.

Cookies

We can get the cookies from the request with the request.cookies.get method.

For example, we can write:

from flask import Flask, request
app = Flask(__name__)

@app.route('/')
def index():
    username = request.cookies.get('username')
    return username

Then when we add the Cookie request header with the value username=foo when we make a GET request to http://127.0.0.1:5000/, then we get the cookie with the key username with request.cookies.get .

It should return 'foo' for username , so that’s what we see in the response body.

Also, we can send cookies with the response.

To do that, we write:

from flask import Flask, make_response, render_template
app = Flask(__name__)

@app.route('/')
def index():
    resp = make_response(render_template('index.html'))
    resp.set_cookie('username', 'the username')
    return resp

We call resp.set_cookie with the key and value of the cookie.

Then we return the response.

Conclusion

We can get request data and send cookie responses with Flask.

Categories
Flask

Python Web Development with Flask — Routes and Templates

Flask is a simple web framework written in Python.

In this article, we’ll look at how to develop simple Python web apps with Flask.

Unique URLs / Redirection Behavior

Adding a trailing slash to the URL will get us to access to the URL with our without a trailing slash.

For example, if we write:

from flask import Flask
app = Flask(__name__)

@app.route('/foo/')
def projects():
    return 'The foo page'

@app.route('/bar')
def about():
    return 'The bar page'

We only see ‘The bar page’ when we go to http://localhost:5000/bar.

On the other hand, if we go to http://localhost:5000/foo or http://localhost:5000/foo/, we see ‘The foo page’.

URL Building

We can use the url_for function to show the full URL of each route.

For example, we can write:

from flask import Flask, url_for
from markupsafe import escape

app = Flask(__name__)

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

@app.route('/login')
def login():
    return 'login'

@app.route('/user/<username>')
def profile(username):
    return '{}'s profile'.format(escape(username))

with app.test_request_context():
    print(url_for('index'))
    print(url_for('login'))
    print(url_for('login', next='/'))
    print(url_for('profile', username='Jane Smith'))

Then in the with block, we print the full paths created from the routes.

We see:

/
/login
/login?next=%2F
/user/Jane%20Smith

url_for('index') returns ‘/‘.

url_for(‘login’) returns '/login' .

url_for(‘login’, next=’/’) returns ‘/login?next=%2F’ .

And url_for(‘profile’, username=’Jane Smith’) returns /user/Jane%20Smith .

We just pass in the function name into url_for as a string, and we get back the URL constructed from it.

HTTP Methods

A route function can take requests made with different HTTP methods.

We can restrict this with the methods parameter we pass into @app.route .

For example, we can write:

from flask import request, Flask
app = Flask(__name__)

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        return 'logged in'
    else:
        return 'login form'

We set the methods parameter to the [‘GET’, ‘POST’] to restrict the function to only accept GET and POST requests.

Then we can check the request method with the request.method property.

So if we make a POST request to http://127.0.0.1:5000/login, we get ‘logged in‘ returned.

And if we make a GET request to the same URL, we get ‘login form‘ returned.

Static Files

We can serve static files with Flask.

To do that, we write:

app.py

from flask import Flask, url_for
app = Flask(__name__)

@app.route('/')
def hello():
    return 'hello world'

with app.test_request_context():
    print(url_for('static', filename='style.css'))

static/style.css

body {
    font-weight: bold;
}

We print the path to the style.css static file in the static folder with the url_for function.

When we go to http://localhost:5000/static/style.css in the browser, we should see:

body {
    font-weight: bold;
}

displayed.

Rendering Templates

To render HTML output, we‘ve to render the content in a template.

To do that, we can use tyhe render_template function by writing:

app.py

from flask import Flask, render_template
app = Flask(__name__)

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)

templates/hello.html

<!doctype html>
<title>Hello from Flask</title>
{% if name %}
  <h1>Hello {{ name }}!</h1>
{% else %}
  <h1>Hello, World!</h1>
{% endif %}

We added a route that optionally takes the name parameter.

Then we call render_template with the path of the template in the templates folder.

Then we pass the variables we want to render into the subsequent arguments.

In hello.html , we check if the name variable is present, if it is, then we display the first message with the name ‘s value.

If we go to http://localhost:5000/hello/james, we see Hello james! displayed.

Otherwise, if we go to http://localhost:5000/hello, we see Hello, world.

Conclusion

We add static files and render templates with Flask.

Categories
Flask

Getting Started with Python Web Development with Flask

Flask is a simple web framework written in Python.

In this article, we’ll look at how to develop simple Python web apps with Flask.

Create the Project

First, we need to install Python 3 if it’s not installed already.

It comes with scripts to create a virtual environment so we don’t have to install anything else.

We can create a project by running:

$ mkdir flask-app
$ cd flask-app
$ python3 -m venv venv

on Linux.

We create the project folder and the virtual environment.

On Windows, we create the flask-app project folder and inside it, we run:

$ py -3 -m venv venv

to create the virtual environment.

Activate the Environment

We then activate the virtual environment.

To do that, we run:

$ . venv/bin/activate

in the project folder in Linux.

On Windows, we run:

> venvScriptsactivate

to do the same thing.

Install Flask

Once we install the virtual environment, we run:

$ pip install Flask

to install the Flask package.

A Minimal App

Now in the flask-app project folder, we create app.py and write:

app = Flask(__name__)

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

to create a hello world app.

Flask(__name__) creates the Flask app.

@app.route is a decorator to add the route.

We return our response to as text in the hello_world function.

Then to run our app, we run:

$ export FLASK_APP=app.py
$ flask run

to run our app on Linux.

On Windows, we run:

> set FLASK_APP=app.py
> python -m flask run

to set the FLASK_APP environment variable and run our app.

The FLASK_APP environment variable should be set to the file name of the entry point.

Now we can go to http://127.0.0.1:5000/ in the browser and see ‘hello world’ displayed on the screen.

Debug Mode

We can turn on debug mode by setting the FLASK_END environment variable to development .

We can run:

export FLASK_ENV=development

to do that on Linux.

On Windows, we run:

set FLASK_ENV=development

to do the same thing.

Routing

We can add more than one route into our app.

For example, we can write:

from flask import Flask
app = Flask(__name__)

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

@app.route('/hello')
def hello():
    return 'Hello, World'

Then when we go to http://127.0.0.1:5000/, we see ‘Welcome’.

And when we go to http://127.0.0.1:5000/hello, we see ‘Hello, World’.

Routing with Variables

We can make our routes more useful with variables.

For example, we can write:

from flask import Flask
from markupsafe import escape
app = Flask(__name__)

@app.route('/user/<username>')
def show_user_profile(username):
    return 'User %s' % escape(username)

@app.route('/post/<int:post_id>')
def show_post(post_id):
    return 'Post %d' % post_id

@app.route('/path/<path:subpath>')
def show_subpath(subpath):
    return 'Subpath %s' % escape(subpath)

to create an app with routes that take route parameters.

<username> is the URL parameter placeholder.

We can access it with the username parameter.

escape escapes the URL parameter so we can use it safely.

We specified the data type it takes with the int and path substrings.

int is an integer. path is a path string.

So if we go to http://localhost:5000/path/foo/bar, we get ‘Subpath foo/bar’.

And if we go to http://localhost:5000/post/2, we get ‘Post 2’.

And if we go to http://localhost:5000/user/foo, we get ‘User foo’.

We can specify the following types:

  • string — accepts any text without a slash (default)
  • int — accepts positive integers
  • float — accepts positive floating-point values
  • path — like string but also accepts slashes
  • uuid — accepts UUID strings

Conclusion

We can create simple apps with ease with Flask.