Flask: Difference between revisions

From wiki
Jump to navigation Jump to search
No edit summary
 
(6 intermediate revisions by the same user not shown)
Line 1: Line 1:
=Installation=
Check this[https://flask.palletsprojects.com/en/1.1.x/quickstart/]
In the directory where you want to create your flask application:
<syntaxhighlight lang=bash>
apt install python3.11-venv  # make sure the venv module is there
python -m venv .venv  # Create a virtual environment
. .venv/bin/activate  # Activate the virtual environment
pip install Flask      # Install flask in the virtual environment
</syntaxhighlight>
=Basics=
=Basics=
Check this[https://flask.palletsprojects.com/en/1.1.x/quickstart/]


Hello world app:
Hello world app:
Line 16: Line 27:


if __name__ == '__main__':        # When executed on the commandline (build in webserver)
if __name__ == '__main__':        # When executed on the commandline (build in webserver)
     app.run(host='0.0.0.0',port=5000) # Listen to localhost port 5000, you can also use flask run for options
     app.run(host='0.0.0.0',port=5000) # Listen to all on port 5000, you can also use flask run for options
     #app.run(host='0.0.0.0',port=8080,Debug=True)  # Run in debug mode, listen to all hosts on port 8080
     #app.run(host='0.0.0.0',port=8080,Debug=True)  # Run in debug mode, listen to all hosts on port 8080


</syntaxhighlight>
</syntaxhighlight>
Run the build-in server listening to all
Or run from the commandline so you can pass options to flask
<syntaxhighlight lang=bash>
<syntaxhighlight lang=bash>
export FLASK_APP=welcome_app.py  
export FLASK_APP=welcome_app.py  
flask run --host=0.0.0.0
flask run --host=0.0.0.0
</syntaxhighlight>
</syntaxhighlight>
Output:
  welcome_app
  welcome_app
   * Serving Flask app "welcome_app"
   * Serving Flask app "welcome_app"
Line 37: Line 49:
Mayor part is from this site [https://vladikk.com/2013/09/12/serving-flask-with-nginx-on-ubuntu/].
Mayor part is from this site [https://vladikk.com/2013/09/12/serving-flask-with-nginx-on-ubuntu/].


* Install [[uwsgi]] it's python plugin.
* Install [[uwsgi]] and uwsgi-plugin-python3.
 
The inifile in
<syntaxhighlight lang="text">
[uwsgi]
base = /var/www/flask/demoapp
plugins = python3
 
# Script to run without .py
app = hello
# It's unclear if the script to run is defined by module or callable
module = %(app)
callable = app
 
home = %(base)/.venv
pythonpath = %(base)
 
#socket file's location and permission
socket = /tmp/%n.sock      # %n is the name of the ini-file without .ini
chmod-socket    = 666
 
#location of log files
logto = /var/log/uwsgi/%n.log  # Funny, logging is done to /var/log/uwsgi/app/%n.log
</syntaxhighlight>


* Create a virtual webserver (port 80 is save enough if you have a secure front-end server)
* Create a virtual webserver (port 80 is save enough if you have a secure front-end server)
Line 49: Line 84:
     server_name <fqdn>;
     server_name <fqdn>;


     location /app1 {
     location @demoapp {
         include uwsgi_params;
         include uwsgi_params;
        uwsgi_param SCRIPT_NAME /app1;
         uwsgi_pass unix://tmp/demoapp_uwsgi.sock;
        uwsgi_modifier1 30;
         uwsgi_pass unix://tmp/app1.sock;
     }
     }
}
}
</syntaxhighlight>
</syntaxhighlight>


=Generate web pages=
That's it. Point your webbrowser to http://<your webserver fdqn></code> and it will show you what the app returns
https://flask.palletsprojects.com/en/1.1.x/patterns/templateinheritance/#template-inheritance
 


[https://www.idkrtm.com/creating-a-webpage-using-python-and-flask/ Source for this basic app]
=Running applications=
 
You can make any number of applications by adding more apps to [[uwsgi]] and a location in [[nginx]]. You can also run any number of programs by adding routes to an app or with just a few routes like this:
Put a index.html in <app-base>/templates/


<syntaxhighlight lang=python>
<syntaxhighlight lang=python>
Line 70: Line 100:


from flask import Flask, render_template
from flask import Flask, render_template
import os
import subprocess


print(__name__)
### Application whitelist
app = Flask(__name__)
whitelist = {
    'script as in URL' :'<scriptlocation>',
    'script as in URL' :'<another scriptlocation>',
    }
   
application = Flask(__name__)


@app.route('/html')
@application.route('/app1/<script>/<path:arguments>')
def static_page():
def func1(script,arguments):
  return render_template('index.html')
    if script in whitelist:
        arglist = arguments.split('/')
        result = subprocess.run([whitelist[script]]+arglist, stdout=subprocess.PIPE)
        output = result.stdout
    else:
        output = '{} does not exist in whitelist'.format(script)
    return output
   
@application.route('/app1/<script>')
def func2(script):
    if script in whitelist:
        result = subprocess.run([whitelist[script]], stdout=subprocess.PIPE)
        output = result.stdout
    else:
        output = '{} does not exist in whitelist'.format(script)
    return output


if __name__ == '__main__':
if __name__ == '__main__':
     app.run(host='0.0.0.0',port=5000,debug=True)
     application.run(host='0.0.0.0', port=8080,debug=True)
 
</syntaxhighlight>
</syntaxhighlight>


=Microservices and/or more applications on 1 web-server=
The route is the request URI as passed by the webserver. In this case 'app1' is the location. The things in <> are converted to python variables. <path:arguments> will put everything, including the '/'-es into 1 variable (arguments). So you can have a variable number of arguments that all will be passed to the pythonscript called by subprocess.


Starting with [https://jawher.me/multiple-python-apps-with-nginx-uwsgi-emperor-upstart/ this page] and additional a lot more we got it working on [https://www.raspberrypi.org/software/ raspberry pi debian].
The whitelist is there for security to avoid one can run any script is knows the location for.


# Make python3 the default<br><code>cd /usr/bin;rm python;ln -s python3 python</code>
=Generate web pages=
# Install uwsgi and python plugin<br><code>apt install uwsgi uwsgi-plugin-python3</code>
# install nginx<br><code>apt install nginx-full</code>
I had to make a small change in the nginx configuration;<br>
<code>vi /etc/nginx/conf.d/my.conf<br>
server_names_hash_bucket_size 64;
</code>


===Super simple apps===
Flask is by default using the [https://jinja.palletsprojects.com jinja] template engine. They have a nice tutorial for this too[https://flask.palletsprojects.com/en/2.0.x/tutorial/].
In /var/www/flask/app1/app1.py
<syntaxhighlight lang=python>
#!/usr/bin/env python3


from flask import Flask
Very simple example is to put a index.html in <code><app-base>/templates/</code>
import os


application = Flask(__name__)
@application.route('/app1')
def app1():
    return "App 1 live and kicking"
if __name__ == '__main__':
    application.run(host='0.0.0.0', port=8080,debug=True)
</syntaxhighlight>
/var/www/flask/app2/app2.py
<syntaxhighlight lang=python>
<syntaxhighlight lang=python>
#!/usr/bin/env python3
#!/usr/bin/env python3


from flask import Flask
from flask import Flask, render_template
import os


application = Flask(__name__)
print(__name__)
app = Flask(__name__)


@application.route('/app2')
@app.route('/app1/html')
def app2():
def static_page():
    return "App 2 live and kicking"
  return render_template('index.html')


if __name__ == '__main__':
if __name__ == '__main__':
     application.run(host='0.0.0.0', port=8080,debug=True)
     app.run(host='0.0.0.0',port=5000,debug=True)
</syntaxhighlight>
 
===Create a nginx virtual host===
 
/etc/nginx/sites-enabled/apps.conf
 
<syntaxhighlight lang=nginx>
server {
  listen 80;
  server_name <your webserver fdqn>;
  index index.html;


  root /var/www/flask;
  location /app1 {
    include uwsgi_params;
    uwsgi_param SCRIPT_NAME /app1;
    uwsgi_modifier1 30;
    uwsgi_pass unix://tmp/app1.sock;
  }
  location /app2 {
    include uwsgi_params;
    uwsgi_param SCRIPT_NAME /app2;
    uwsgi_modifier1 30;
    uwsgi_pass unix://tmp/app2.sock;
  }
}
</syntaxhighlight>
</syntaxhighlight>
===Start things===
<syntaxhighlight lang=bash>
service uwsgi start
service nginx start
</syntaxhighlight>
That's it. Point your webbrowser to http://<your webserver fdqn>/app1
Optimization still to be done. I think I start on [https://www.techatbloomberg.com/blog/configuring-uwsgi-production-deployment/ this place]

Latest revision as of 20:10, 10 June 2025

Installation

Check this[1]

In the directory where you want to create your flask application:

apt install python3.11-venv  # make sure the venv module is there
python -m venv .venv   # Create a virtual environment
. .venv/bin/activate   # Activate the virtual environment
pip install Flask      # Install flask in the virtual environment

Basics

Hello world app:

#!/usr/bin/env python3

from flask import Flask
print(__name__)
app = Flask(__name__)

@app.route('/')

def welcome():
    return 'Welcome'

if __name__ == '__main__':         # When executed on the commandline (build in webserver)
    app.run(host='0.0.0.0',port=5000) # Listen to all on port 5000, you can also use flask run for options
    #app.run(host='0.0.0.0',port=8080,Debug=True)  # Run in debug mode, listen to all hosts on port 8080

Or run from the commandline so you can pass options to flask

export FLASK_APP=welcome_app.py 
flask run --host=0.0.0.0

Output:

welcome_app
 * Serving Flask app "welcome_app"
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

Now you can browse to <serverIP>:5000

https://code.tutsplus.com/tutorials/creating-a-web-app-from-scratch-using-python-flask-and-mysql--cms-22972

Integrate with nginx

Mayor part is from this site [2].

  • Install uwsgi and uwsgi-plugin-python3.

The inifile in

[uwsgi]
base = /var/www/flask/demoapp
plugins = python3

# Script to run without .py
app = hello
# It's unclear if the script to run is defined by module or callable
module = %(app)
callable = app

home = %(base)/.venv
pythonpath = %(base)

#socket file's location and permission
socket = /tmp/%n.sock      # %n is the name of the ini-file without .ini
chmod-socket    = 666

#location of log files
logto = /var/log/uwsgi/%n.log   # Funny, logging is done to /var/log/uwsgi/app/%n.log
  • Create a virtual webserver (port 80 is save enough if you have a secure front-end server)
server {
    listen 80 ;
    listen [::]:80;

    root /var/www/flask;
    server_name <fqdn>;

    location @demoapp {
        include uwsgi_params;
        uwsgi_pass unix://tmp/demoapp_uwsgi.sock;
    }
}

That's it. Point your webbrowser to http://<your webserver fdqn> and it will show you what the app returns

Running applications

You can make any number of applications by adding more apps to uwsgi and a location in nginx. You can also run any number of programs by adding routes to an app or with just a few routes like this:

#!/usr/bin/env python3

from flask import Flask, render_template
import os
import subprocess 

### Application whitelist
whitelist = {
    'script as in URL' :'<scriptlocation>',
    'script as in URL' :'<another scriptlocation>',
    }
    
application = Flask(__name__)

@application.route('/app1/<script>/<path:arguments>')
def func1(script,arguments):
    if script in whitelist:
        arglist = arguments.split('/')
        result = subprocess.run([whitelist[script]]+arglist, stdout=subprocess.PIPE)
        output = result.stdout
    else:
        output = '{} does not exist in whitelist'.format(script)
    return output
    
@application.route('/app1/<script>')
def func2(script):
    if script in whitelist:
        result = subprocess.run([whitelist[script]], stdout=subprocess.PIPE)
        output = result.stdout
    else:
        output = '{} does not exist in whitelist'.format(script)
    return output

if __name__ == '__main__':
    application.run(host='0.0.0.0', port=8080,debug=True)

The route is the request URI as passed by the webserver. In this case 'app1' is the location. The things in <> are converted to python variables. <path:arguments> will put everything, including the '/'-es into 1 variable (arguments). So you can have a variable number of arguments that all will be passed to the pythonscript called by subprocess.

The whitelist is there for security to avoid one can run any script is knows the location for.

Generate web pages

Flask is by default using the jinja template engine. They have a nice tutorial for this too[3].

Very simple example is to put a index.html in <app-base>/templates/

#!/usr/bin/env python3

from flask import Flask, render_template

print(__name__)
app = Flask(__name__)

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

if __name__ == '__main__':
    app.run(host='0.0.0.0',port=5000,debug=True)