A Simple Python Flask Web App

There are times when you need a very simply tool to do something rather trivial that needs to be accessible to various users. If it’s simple enough it seems rather silly to stand a server and install Apache to make some simple configuration changes. This is where Flask can shine. Let’s take a look at a simple tool that I wrote, which took less than an hour.

First thing is first, install Flask 2.0. I did not create a virtual environment for this but I would suggest you do so with Python version 2.9.

$ pip install flask

Next create a folder to hold the files. Here is the structure I used:

~/proxy
    flasky.py
    /templates/proxy.html
    /templates/help.html
    /static/css/  (Bootstrap CSS)
    /static/js/   (Bootstrap and Jquery libs)
    /static/images/logo-sm.png

You need Bootstrap v5.1.1 and JQuery v3.6.0

Place the JQuery and Bootstrap JS files in /js and the Bootstrap CSS in /css. The image logo is 163x50px and lives in /images.

We need two html files created in /templates: proxy.html

    <title>My Little Proxy</title>

    <link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">
    <script src="{{ url_for('static', filename='js/bootstrap.bundle.min.js') }}"></script>
    <script src="{{ url_for('static', filename='js/jquery-3.6.0.min.js') }}"></script>

    <style>
        body {
            background-color: #FAFCFF;
            font-family: Verdana, Geneva, sans-serif;
            font-size:16px;
        }

        .input-group-text, .btn, li {
            font-weight: bold;
        }

        span.footer {
            color: #FAFCFF;
            font-size:14px;
        }

        button {
            width: 70px;
        }
    </style>
</head>

<body>
    <header style="margin: 0 0 25px 0; padding: 0;">
        <nav class="navbar navbar-expand-lg navbar-dark bg-dark" style="padding: 0px;">
            <div class="container-fluid">
                <a class="navbar-brand" href="#"><img src="{{ url_for('static', filename='images/logo-sm.png') }}" alt="My Little Proxy" /></a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navbarSupportedContent" style="padding-bottom: 0; margin-top: 25px;">
                    <ul class="navbar-nav me-auto mb-2 mb-lg-0" style="padding: 0px; margin-bottom: 0;">
                        <li class="nav-item dropdown">
                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                            Dropdown
                            </a>
                            <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
                                <li><a class="dropdown-item" href="#">Action</a></li>
                                <li><a class="dropdown-item" href="#">Another action</a></li>
                                <li><hr class="dropdown-divider"></li>
                                <li><a class="dropdown-item" href="#">Something else here</a></li>
                            </ul>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="http://localhost:5000/help/">Help</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>

    <div class="container">

        <div style="width: 500px; margin-left: auto; margin-right: auto;">
            <h4>My Little Proxy Configuration</h4>
            <p>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
            </p>
        </div>

        <form action="/proxy" method = "POST" style="width: 500px; margin-left: auto; margin-right: auto;">
            <div class="input-group input-group-sm mb-3">
                <span class="input-group-text" id="basic-addon1" style="width: 70px">Name</span>
                <input type="text" class="form-control" name="name" placeholder="Your name..." required>
            </div>

            <div class="input-group input-group-sm mb-3">
                <span class="input-group-text" id="basic-addon1" style="width: 70px">Age</span>
                <input type="text" class="form-control" name="age" placeholder="Your age..." required>
            </div>

            <div class="input-group input-group-sm mb-3">
                <span class="input-group-text" id="basic-addon1" style="width: 70px">Gender</span>
                <input type="text" class="form-control" name="gender" placeholder="Your gender..." required>
            </div>

            <div class="mb-3">
                <button class="btn btn-secondary btn-sm" type="reset">Clear</button>
                <button class="btn btn-primary btn-sm float-end" type="submit">Save</button>
            </div>

            {% if form_data: %}
                {% if "error" in form_data: %}
                    <div class="alert alert alert-danger alert-dismissible fade show shadow-danger" role="alert" id="alert_message">
                        {% for key,value in form_data.items() %}
                        <p><h2>{{key}}</h2> {{value}}</p>
                        {% endfor %}
                        <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close" ></button>
                    </div>
                {% else %}
                    <div class="alert alert-success alert-dismissible fade show shadow-success" role="alert" id="alert_message">
                        {% for key,value in form_data.items() %}
                        <p><h2>{{key}}</h2> {{value}}</p>
                        {% endfor %}
                        <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close" ></button>
                    </div>
                {% endif %}
            {% endif %}
        </form>
    </div>

    <footer class="footer fixed-bottom mt-auto py-2 bg-dark" style="margin: 15px 0 0 0;">
        <div class="container" style="text-align: center; margin-left: auto; margin-right: auto;">
            <span class="footer text-muted"><a href="mailto:linuxteam@host.com">Linux Team</a> Proxy Utility.</span>
        </div>
    </footer>

    <script>
        $( document ).ready(function() {
            $( "#alert_message" ).fadeIn( 300 ).delay( 2500 ).fadeOut( 400 );
        });
    </script>
</body>

help.html

    <title>My Little Proxy - Help</title>

    <link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">
    <script src="{{ url_for('static', filename='js/bootstrap.bundle.min.js') }}"></script>
    <script src="{{ url_for('static', filename='js/jquery-3.6.0.min.js') }}"></script>

    <style>
        body {
            background-color: #FAFCFF;
            font-family: Verdana, Geneva, sans-serif;
            font-size:16px;
        }

        span.footer {
            color: #FAFCFF;
            font-size:14px;
        }

        .btn {
            font-weight: bold;
        }

        button {
            width: 70px;
        }
    </style>
</head>

<body>
    <header style="margin: 0 0 25px 0; padding: 0;">
        <nav class="navbar navbar-expand-lg navbar-dark bg-dark" style="padding: 0px;">
            <div class="container-fluid">
                <a class="navbar-brand" href="#"><img src="{{ url_for('static', filename='images/logo-sm.png') }}" alt="My Little Proxy" /></a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navbarSupportedContent" style="padding-bottom: 0; margin-top: 25px;">
                    <ul class="navbar-nav me-auto mb-2 mb-lg-0" style="padding: 0px; margin-bottom: 0;">
                        <li class="nav-item dropdown">
                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                            Dropdown
                            </a>
                            <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
                                <li><a class="dropdown-item" href="#">Action</a></li>
                                <li><a class="dropdown-item" href="#">Another action</a></li>
                                <li><hr class="dropdown-divider"></li>
                                <li><a class="dropdown-item" href="#">Something else here</a></li>
                            </ul>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="#" style="font-style: italic;">Help</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>

    <div class="container">
        <div style="width: 500px; margin-left: auto; margin-right: auto;">
            <h4>Help</h4>
            <p>
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
            </p>
            <a class="btn btn-primary btn-sm" href="http://localhost:5000/proxy/" role="button">Back</a>
        </div>
    </div>

    <footer class="footer fixed-bottom mt-auto py-2 bg-dark" style="margin: 15px 0 0 0;">
        <div class="container" style="text-align: center; margin-left: auto; margin-right: auto;">
            <span class="footer text-muted"><a href="mailto:linuxteam@host.com">Linux Team</a> Proxy Utility.</span>
        </div>
    </footer>
</body>

The heart of the program is the Python code. This live in ~/proxy: flasky.py

#!/usr/bin/env python
from flask import Flask, render_template, request, redirect, url_for
from markupsafe import escape
import json
'''
https://flask.palletsprojects.com/en/2.0.x/ : pip install flask
https://getbootstrap.com/
https://jquery.com
'''

app = Flask(__name__)

@app.route('/help/', methods = ['GET'])
def hello_world():
   return render_template('help.html')

@app.route('/proxy/', methods = ['POST', 'GET'])
def data():
    if request.method == 'GET':
        return render_template('proxy.html')
    
    if request.method == 'POST':
        form_data = request.form 
        is_okay = process_form(form_data)
        if not is_okay:
            form_data = {'error': 'message'}
        return render_template('proxy.html', form_data = form_data)
    
def process_form(data):
    processed = False
    
    if data.get('name') == 'piss': 
        return False
    
    try:
        jsonofied = json.dumps(data)
        processed = True
    except:
        pass        
    return processed
  
if __name__ == "__main__":
    app.run(host='localhost', port=5000)

Yes, amazingly that’s it! To start the server just open the terminal in the proxy folder and type: python flasky.py and hit the browser address: http://localhost:5000/proxy/

If it fails make sure the port is available.

See it in action: