This shows you the differences between two versions of the page.
ii:labs:s2:03 [2022/03/30 20:13] florin.stancu created |
ii:labs:s2:03 [2024/04/01 21:58] (current) florin.stancu |
||
---|---|---|---|
Line 1: | Line 1: | ||
~~NOTOC~~ | ~~NOTOC~~ | ||
- | ====== Lab 03 - TODO ====== | + | ====== Lab 03 - Advanced Flask ====== |
+ | |||
+ | ==== Objectives ==== | ||
+ | |||
+ | * Advanced Flask concepts | ||
+ | * Jinja Templates | ||
+ | * Cookies, Sessions & Authentication | ||
+ | * Storing and retrieving data from databases | ||
+ | * Advanced HTTP: file uploading | ||
+ | |||
+ | ===== Contents ===== | ||
+ | |||
+ | **Tasks** | ||
+ | {{indexmenu>:ii:labs:s2:03:tasks|skipfile}} | ||
+ | |||
+ | ===== Introduction ===== | ||
+ | |||
+ | This lab will take you through more advanced server-side concepts in Flask: templates, sessions, authentication and file upload (bonus). | ||
+ | |||
+ | === Template Engines === | ||
+ | |||
+ | A typical website has a common HTML design, with only portions of its code changing on a per-page basis with specific content. | ||
+ | In order to prevent needless code duplication, a **template engine** is usually employed to obtain HTML documents from common layouts. A template is, basically, a HTML page interleaved with specific code blocks used to insert dynamically generated content from variables; many engines feature full programming languages that support loops and conditionals. | ||
+ | |||
+ | Flask readily integrates with the [[https://jinja.palletsprojects.com/en/3.1.x/templates/|Jinja templating engine]] which uses Python-like statements to enrich a HTML page with programmatic content: | ||
+ | <code html> | ||
+ | <!-- ... --> | ||
+ | <body> | ||
+ | <h1>My Webpage is {{ awesome_variable }}</h1> | ||
+ | |||
+ | <ul id="main-menu"> | ||
+ | {% for item in navigation %} | ||
+ | <li><a href="{{ item.href }}">{{ item.caption }}</a></li> | ||
+ | {% endfor %} | ||
+ | </ul> | ||
+ | |||
+ | {# a comment #} | ||
+ | </body> | ||
+ | </code> | ||
+ | |||
+ | The Jinja templates usually reside inside the project's ''templates/'' directory (check the [[https://flask.palletsprojects.com/en/3.0.x/api/#application-object|Flask documentation]] if you want to change it) and can be rendered using the ''[[https://flask.palletsprojects.com/en/3.0.x/api/#template-rendering|render_template]]'' utility function. | ||
+ | |||
+ | === Persisting sessions. User Authentication === | ||
+ | |||
+ | HTTP is a stateless protocol, which means that any request (e.g., from a browser) must not assume that the server knows any of its historic actions. | ||
+ | |||
+ | To persist the state, servers often use the cookie feature to establish so-called **sessions**, simple key-value pairs which can either be stored inside the client's cache/memory (encrypted, of course) or on server-side (hence client will only store an unique identifier issued by the server, and the server will have a database entry for each client ID with its private session data). | ||
+ | |||
+ | When a session-based request arrives on the server, it reads the cookie, decodes the ID or retrieves the session data from its database and exposes session context variables to the application developers. In flask, the ''session'' global var is uses exactly for this: <code Python> | ||
+ | from flask import ..., session | ||
+ | # ... | ||
+ | @app.route("/") | ||
+ | def account_page(): | ||
+ | if "authenticated" not in session: | ||
+ | return redirect("/login", code=302) | ||
+ | # ... | ||
+ | </code> | ||
+ | |||
+ | Since the session data store is properly authenticated and encrypted, it is often used to provide a persistent authentication of the client (e.g., using the results from a login form), though server may also use its session to track the user's behavior (e.g., the pages it opened in the last minute, zones clicked etc.). | ||
+ | |||
+ | === Persisting data on the server. === | ||
+ | |||
+ | Sessions are often lost when either the server or the client browser is restarted (since they are stored in-memory or limited cache). | ||
+ | |||
+ | If a server wishes to store long-term persistent data, a database is the standard way to ensure data availability. | ||
+ | |||
+ | Databases are often fully-fledged applications in their own right and the web server communicates with them using various inter-process or socket-based channels (though client libraries are always provided), either using separate language (e.g., SQL) or specific/proprietary APIs (no-SQL). | ||
+ | |||
+ | But, for today, a simple disk-based file stored on the server will suffice (you should know how to do this in Python) ;) | ||
+ | |||
+ | ===== Preparation ===== | ||
+ | |||
+ | Reminder to create your virtualenv and install Flask inside: | ||
+ | <code bash> | ||
+ | # either you or your IDE should create the Python Virtual Environment, e.g.: | ||
+ | python3 -m venv .venv | ||
+ | # activate it (note: you will need to do this every time you change your shell)! | ||
+ | source .venv/bin/activate | ||
+ | # finally, install libraries using pip | ||
+ | python3 -m pip install flask | ||
+ | </code> | ||
+ | |||
+ | ===== Tasks ===== | ||
+ | |||
+ | {{namespace>:ii:labs:s2:03:tasks&nofooter&noeditbutton}} | ||