Flask: Difference between revisions

From XPUB & Lens-Based wiki
No edit summary
 
(61 intermediate revisions by one other user not shown)
Line 1: Line 1:
=Flask=  
==Flask==
Short introduction guide on Flask.
http://flask.pocoo.org/
(Used for XPPL, so to see a more advanced use in connection with database, see [[XPPL]])


==Basic Flask==
https://flask.palletsprojects.com/


Flask is a microframework for python to create web applications. It basically connects the webserver with your python code.
Flask is a microframework for python to create web applications. It basically connects the webserver with your python code, and it uses Jinja as a template engine.  
 
So basically... it brings HTML + CSS + PYTHON + JINJA together!
 
===Documentation===
 
* Flask: https://flask.palletsprojects.com/en/stable/quickstart/
* Jinja: https://jinja.palletsprojects.com/en/stable/templates/
 
===Flask in practice===
 
Flask was used in the past for different things at XPUB, including the [[XPPL]], [https://project.xpub.nl/frabjousish/ Euna's graduation work Frabjousish], the [[Padliography]] made by Kamo, [https://cc.practices.tools/wiki/Octomode octomode] made by Manetta, and ... more!
 
Flask is something that you can use to make things like interactive web pages and artistic tools. It's not too difficult to work with and can do great stuff!
 
It's great for connecting the operating system of your computer/server with a web page.
 
⚠ '''However''' ⚠
 
* dynamic, not static
* relies on full server access (web-hosting is not enough)
** alternative: php
** alternatice: javascript + node
* adding layers of complexity: nginx, background service
* can quickly disappear (harder to archive compared to static pages)
* and! the trap of making something "interactive"
* also: security is something to keep into account
 
So never forget to keep in mind:
 
* how can this project be archived? (for example: static export)
* for who are you making this interactive thing?
* how public are my POST requests


===Install===
===Install===
<pre>
 
$ pip install Flask
with uv:
</pre>
 
$ uv venv
$ source .venv/bin/activate
$ uv pip install flask
 
or just with a python virtual environment:
 
$ python3 -m venv venv
$ source venv/bin/activate
$ pip install flask


===Simple text serving===
===Simple text serving===
Line 26: Line 64:
* the function definition after is mandetory as well as the return.  
* the function definition after is mandetory as well as the return.  
* everything that comes after return gets sent back to the browser (http GET request)
* everything that comes after return gets sent back to the browser (http GET request)
Save the code above as <code>hello.py</code>.


Run it with:
Run it with:
<pre>
 
$ FLASK_APP=hello.py flask run
$ flask --app hello run
</pre>
 
And if you want to enable the debugger (recommended!):
 
$ flask --app hello --debug run


== Paths ==
== Paths ==
Line 51: Line 94:
</pre>
</pre>


== Http Methods ==
== HTTP Methods ==


Methods like GET or POST (DELETE, PUT…) can be handled by flask
Methods like GET or POST (DELETE, PUT…) can be handled by flask
Line 67: Line 110:
         answer = "get"
         answer = "get"
     if request.method == 'POST':
     if request.method == 'POST':
         answer = "get"
         answer = "post"
     return answer
     return answer
</pre>
</pre>
Line 83: Line 126:
</pre>
</pre>


you can pass as many variables to the template as you want. in this example we pass message to the template:
You can pass as many variables to a template and keep the code separate from the HTML it generates. In this example we pass message to this template:


The html looks something like:
<pre>
<pre>
<html>
<p>{{ message }}</p>
<p>{{message}}</p>
<html>
</pre>
</pre>


'''!important:''' The html file needs to be saved inside a templates folder called "templates" inside your project folder-
'''!important:''' The template file needs to be saved inside a templates folder called "templates" inside your project folder, this is a Flask default.


== Helpful function ==
== Helpful function ==
Line 103: Line 143:
</pre>
</pre>


== Deploying ==
==Examples==
 
===Observations===
 
''This prototype is prepared for class during [[SI30]] in April 2026.''
 
''It is installed on sergio, here: https://hub.xpub.nl/sergio/SI30/fieldwork-tools/example/''
 
[[File:Screenshot from 2026-04-01 16-13-15.png|thumb|A field work tool prototype made in Flask.]]
 
To run this example, you can use this command:
 
flask --app observations --debug run
 
Make a folder for this flask application.
 
Install a venv + flask in this folder:
 
cd /path/to/your/folder/
uv venv
uv pip install flask
 
Save the files below in this folder, it should look like this:
 
<pre>.
├── observations.py
└── templates
    └── observations.html
</pre>
 
====Python script====


=== Running with uwsgi ===
<code>observations.py</code>


Flask warns you that using "the development server" isn't good for "production use".
<syntaxhighlight lang="python">
from flask import Flask, render_template, request
app = Flask(__name__)


Using software like uwsgi to run your flask project on a server is a good idea. It:
@app.route("/", methods=["GET", "POST"])
* Is able to deal with many users at the same time
def main():
* When configured right lets large static files (like images / videos) be served in a way that works well
    if request.method == "POST":
        observation = request.form["observation"]
       
        # WRITE TO DATABASE
        with open("database.txt", "a") as database:
            database.write(observation + "\n")
   
    # READ DATABASE
    database = open("database.txt", "r").readlines()
   
    return render_template("observations.html", database=database)
</syntaxhighlight>


https://hackersandslackers.dev/deploy-flask-uwsgi-nginx/
====Template====


=== Making the systemd service file ===
<code>templates/observations.html</code>


See: https://blog.miguelgrinberg.com/post/running-a-flask-application-as-a-service-with-systemd
<syntaxhighlight lang="html">
<style>
body{
    text-align: center;
}
div#archive{
    background-color: lightgray;
    padding: 1em;
}
div.observation{
    background-color: white;
    border: 1px solid black;
    padding: 1em;
    margin: 0.5em 0;
}
form{
    margin: 1em;
}
form textarea{
    width: 100%;
    height: 200px;
}
form input{
    margin-top: 1em;
    font-size: 12pt;
}
</style>


Useful: https://containersolutions.github.io/runbooks/posts/linux/debug-systemd-service-units/
<h1>My observations</h1>


  sudo nano /etc/systemd/system/myflaskapp.service
<div id="archive">
{% for observation in database %}
<div class="observation">{{ observation }}</div>
{% endfor %}
</div>


<source>
<form method="POST">
[Unit]
    <textarea name="observation"></textarea>
Description=<a description of your application>
    <input type="submit" value="SAVE">
After=network.target
</form>
</syntaxhighlight>


[Service]
===My Unicode converter===
User=<username>
WorkingDirectory=<path to your app>
ExecStart=<app start command>
Restart=always


[Install]
[[File:Screenshot from 2026-04-07 13-04-12.png|thumb|Example of a flask application that converts characters to unicode points]]
WantedBy=multi-user.target
 
</source>
This is a small flask application that converts character into unicode points. It is made to show how you can make tiny tools, and how you can connect python to the web.  
 
<syntaxhighlight lang="python">
from flask import Flask, request
app = Flask(__name__)


html_template = """
<h1>transformations</h1>
<form action="/" method="post">
<input type="text" name="search">
<br><br>
<input type="submit" value="transform">
</form>
"""


When the service file is new or changed, you need (one time) to:
@app.route("/", methods=["POST","GET"])
def transformations():
    if request.method == "POST":


    sudo systemctl daemon-reload
        search = request.form["search"]
       
        result_list = []
        for character in search:
            unicode_point = format(ord(character))
            result_list.append(character + " " + unicode_point)


Then you can:
        result_string = "<br>\n".join(result_list)


     sudo systemctl status myflaskapp
        return html_template + f"<pre>{ result_string }</pre>"
     sudo systemctl restart myflaskapp
      
     sudo systemctl stop myflaskapp
     if request.method == "GET":
      
        return html_template
</syntaxhighlight>


'''Then finally''' when you see that start works (checking status, checking that it actually is running , etc)
==Install on a server==


    sudo systemctl enable myflaskapp
See: [[Install on a server]]


Will make the "service" auto start when the pi restarts.
==See also==


To view the log file (errors):
* [[File uploads on a web page]] using Flask
* [[Flask in a container]] by Tommi


    sudo journalctl -u myflaskapp -f
[[Category:Raspberry Pi]] [[Category:flask]]

Latest revision as of 13:59, 7 July 2026

Flask

https://flask.palletsprojects.com/

Flask is a microframework for python to create web applications. It basically connects the webserver with your python code, and it uses Jinja as a template engine.

So basically... it brings HTML + CSS + PYTHON + JINJA together!

Documentation

Flask in practice

Flask was used in the past for different things at XPUB, including the XPPL, Euna's graduation work Frabjousish, the Padliography made by Kamo, octomode made by Manetta, and ... more!

Flask is something that you can use to make things like interactive web pages and artistic tools. It's not too difficult to work with and can do great stuff!

It's great for connecting the operating system of your computer/server with a web page.

However

  • dynamic, not static
  • relies on full server access (web-hosting is not enough)
    • alternative: php
    • alternatice: javascript + node
  • adding layers of complexity: nginx, background service
  • can quickly disappear (harder to archive compared to static pages)
  • and! the trap of making something "interactive"
  • also: security is something to keep into account

So never forget to keep in mind:

  • how can this project be archived? (for example: static export)
  • for who are you making this interactive thing?
  • how public are my POST requests

Install

with uv:

$ uv venv
$ source .venv/bin/activate
$ uv pip install flask

or just with a python virtual environment:

$ python3 -m venv venv
$ source venv/bin/activate
$ pip install flask

Simple text serving

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"
  • with @app.route you can define the url flask respons to.
  • the function definition after is mandetory as well as the return.
  • everything that comes after return gets sent back to the browser (http GET request)

Save the code above as hello.py.

Run it with:

$ flask --app hello run

And if you want to enable the debugger (recommended!):

$ flask --app hello --debug run

Paths

You can use any route you like

@app.route("/any/route/you/like")

You can also use variable routes (example for int)

@app.route("/book/<int:id>")
def book(id):

as you can see you can grab the variable in the url through the function’s parameter

(example for string)

@app.route("/book/<bookname>")
def book(bookname):

HTTP Methods

Methods like GET or POST (DELETE, PUT…) can be handled by flask

Therefore you need to add the wanted methods to the route definition like:

from flask import Flask
app = Flask(__name__)

@app.route('/address_to_post', methods= ['POST','GET'])
def respond_to_post():
    answer = ""
    if request.method == 'GET':
        answer = "get"
    if request.method == 'POST':
        answer = "post"
    return answer

with request.method you can determine the incoming kind of request.

Templates

To be able return full html pages, flask uses templates using Jinja to insert variable content.

@app.route('/')
def home():
    message = "Welcome Home!"
    return render_template('home.html', message=message)

You can pass as many variables to a template and keep the code separate from the HTML it generates. In this example we pass message to this template:

<p>{{ message }}</p>

!important: The template file needs to be saved inside a templates folder called "templates" inside your project folder, this is a Flask default.

Helpful function

404 Page not found

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

Examples

Observations

This prototype is prepared for class during SI30 in April 2026.

It is installed on sergio, here: https://hub.xpub.nl/sergio/SI30/fieldwork-tools/example/

A field work tool prototype made in Flask.

To run this example, you can use this command:

flask --app observations --debug run

Make a folder for this flask application.

Install a venv + flask in this folder:

cd /path/to/your/folder/
uv venv
uv pip install flask 

Save the files below in this folder, it should look like this:

.
├── observations.py
└── templates
    └── observations.html

Python script

observations.py

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

@app.route("/", methods=["GET", "POST"])
def main():
    if request.method == "POST":
        observation = request.form["observation"]
        
        # WRITE TO DATABASE
        with open("database.txt", "a") as database:
            database.write(observation + "\n")
    
    # READ DATABASE
    database = open("database.txt", "r").readlines()
    
    return render_template("observations.html", database=database)

Template

templates/observations.html

<style>
body{
    text-align: center;
}
div#archive{
    background-color: lightgray;
    padding: 1em;
}
div.observation{
    background-color: white;
    border: 1px solid black;
    padding: 1em;
    margin: 0.5em 0;
}
form{
    margin: 1em;
}
form textarea{
    width: 100%;
    height: 200px;
}
form input{
    margin-top: 1em;
    font-size: 12pt;
}
</style>

<h1>My observations</h1>

<div id="archive">
{% for observation in database %}
<div class="observation">{{ observation }}</div>
{% endfor %}
</div>

<form method="POST">
    <textarea name="observation"></textarea>
    <input type="submit" value="SAVE">
</form>

My Unicode converter

Example of a flask application that converts characters to unicode points

This is a small flask application that converts character into unicode points. It is made to show how you can make tiny tools, and how you can connect python to the web.

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

html_template = """
<h1>transformations</h1>
<form action="/" method="post">
<input type="text" name="search">
<br><br>
<input type="submit" value="transform">
</form>
"""

@app.route("/", methods=["POST","GET"])
def transformations():
    if request.method == "POST":

        search = request.form["search"]
        
        result_list = []
        for character in search:
            unicode_point = format(ord(character))
            result_list.append(character + " " + unicode_point)

        result_string = "<br>\n".join(result_list)

        return html_template + f"<pre>{ result_string }</pre>"
    
    if request.method == "GET":
    
        return html_template

Install on a server

See: Install on a server

See also