As you could read previously, Flask is a very powerful #Python microframework for web programming, and it’s the one I’ve chosen to work with. I could select others, because the differences between one or other are small details, and migrating from one framework to another is not a difficult task. So, let’s start with Flask.
“Hello world” in Flask
This is the first example, and you can find it in several webs, such as here: https://realpython.com/blog/python/introduction-to-flask-part-1-setting-up-a-static-site/. I will be commenting the code, instead of repeating the code one more time.
First, every project should be initialize in a new directory. The recommendation is tu use virtualenv for creating an “exclusive” environment to work with, but I decided not to do it, and install everything I need in the Python directory.
Once you have the working dir ready, you need to create two sub-directories: templates and static. The first one is the place where you have your HTML5 templates, where on the second subdir you have static files such as CSS, Javascript, …
This is, pore or less, the base for small projects, although this can be improved.
Another good reference to start with Flask is this tutsplus tutorial.
But, indeed, the best recommendation I can give you is to read the official doccumentation: https://flask.palletsprojects.com/en/1.1.x/.
The second project
In this second project, let’s see how you can call to several HTML pages, and also, you can force to be logged in to see internal pages, by using decorators. You can read more about decorators here.
Let’s start with this second project. First, let define the HTML pages, and this way, I’ll introduce you how to use templates, that are stored in the templates directory. The code for base.html will be the base for generating a template system. I would like to mention the use of url_for because is a function for creating URLs (a Flask characteristic). The use of this function modify a bit how CSS, Javascript, …. are loaded into the HTML, a bit strange, but very effective!
Here, I have used both forms for you, to decide which one do you like more!
The base.html code is:
<!DOCTYPE html> <html> <head> <title>Jugando con Flask - Manejando datos.es</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link href="static/css/bootstrap.min.css" rel="stylesheet" media="screen"> <link id="pure" href="{{ url_for('static', filename='css/purecss-min.css') }}" rel="stylesheet"> <link id="pure" href="{{ url_for('static', filename='css/manejandodatos_purecss.css') }}" rel="stylesheet"> </head> <body> <header> <h1>Probando Flask desde Manejando datos</h1> </header> <div class="container"> <!-- child template --> {% block content %}{% endblock %} <!-- errors --> {% if error %} <p class="error"><strong>Error:</strong> {{ error }}</p> {% endif %} <!-- messages --> {% for message in get_flashed_messages() %} {{ message }} {% endfor %} </div> <footer> <h6> Creado desde <a target="_blank" href="http://www.manejandodatos.es">Manejando datos</a> </h6> </footer> </body> </html>
I have used Twitter Bootstrap y PureCSS for the CSS, that you are already know about them.
Now, turn for index.html, which is based on base.html. You notice that because the extends keyword.
{% extends "base.html" %} {% block content %} <h1>Welcome to Flask!</h1> <br> <h3>Posts:</h3> {% for post in posts %} <h1> {{ post.title }}</h1> {{ post.description }} <br> <br> {% endfor %} {% endblock %}
Let’s create a welcome page, saludo.html:
{% extends "base.html" %} {% block content %} <h2>Saludo desde Flask!</h1> <br> <p>volver a pagina <a href="/">principal</a>.</p> {% endblock %}
and a private page, called privada.html, who’s HTML code is:
{% extends "base.html" %} {% block content %} <h2>Página privada!</h1> <br> <p>Volver a pagina <a href="/">principal</a> o ir a <a href="/saludo" class="pure-button">saludo</a>.</p> Pulse para <a href="/logout" class="pure-button">salir</a>!! {% endblock %}
Let’s change of language, and it’s Python turn. Let’s start with run.py. On this file is where Flask is loaded, and yoy start calling pages:
from flask import Flask, render_template, url_for, redirect app = Flask(__name__) methods = ['GET', 'POST'] GET, POST = methods @app.route('/') def home(): return render_template('index.html') @app.route('/saludo') def saludo(): return render_template('saludo.html') @app.route('/privada') def privada(): return render_template('privada.html') if __name__ == '__main__': app.run(debug=True)
This is the first version, and the main goal is how you can show 3 different HTML pages, and move from one to another. As you can see, the Python code is not difficult, because using render_template is the way to call to HTML templates.
Increasing difficulty
Now, let’s create a new version of the previous code, run2.py, by adding the neccesary code to access only the provate HTML pages when you are logged in. So, let’s create a template for the login form:
from flask import Flask, render_template, url_for, redirect, flash, session, request from functools import wraps app = Flask(__name__) app.secret_key = "flask_manejandodatos.es" methods = ['GET', 'POST'] GET, POST = methods def requiere_login(f): @wraps(f) def wrap(*args, **kkargs): if 'logged_in' in session: return f(*args, **kkargs) else: flash('Necesitas hacer LogIn antes!') return redirect(url_for('login')) return wrap @app.route('/') def home(): return render_template('index.html') @app.route('/saludo') def saludo(): return render_template('saludo.html') @app.route('/privada') @requiere_login def privada(): return render_template('privada.html') @app.route('/login', methods=methods) def login(): error = None if request.method == POST: if request.form['username'] != 'admin' or request.form['password'] != 'admin': error = 'Error en las credenciales' else: session['logged_in'] = True flash('Estas dentro') return redirect(url_for('home')) return render_template('login.html', error=error) @app.route('/logout') def logout(): session.pop('logged_in', None) flash('Estas fuera') print "Logout" return redirect(url_for('home')) if __name__ == '__main__': app.run(debug=True)
As you can see, all templates are extends by using base.html.
In this new version, you have a decorator and you modify the behaviour when the private page is called. Also, you need to control the data of the login form (it’s very basic here, but the normal way of doing this is by connecting to a database to verify the user is valid!).
Another yet important aspect of this run2.py code is the private key used in the app, and the session object, that is the one that control if you are logged in or not.
I have uploaded the code to GitHub, both versions.
I hope you enjoy!