Lesson 4
Using Sessions to Manage Theme Preference
Using Sessions to Manage Theme Preference

Welcome back! As we continue to enhance our Flask ToDo application, let's delve into the use of sessions. In web development, a session is a way to store information specific to a user across multiple requests. This is extremely useful for personalizing the user's experience, such as by keeping track of their preferred theme.

In this lesson, we'll focus on how to use Flask sessions to allow users to switch between a light and dark theme in our ToDo application. By the end of this lesson, you'll know how to implement a session-based theme management system and understand the practical application of sessions in a real-world scenario.

What Are Sessions?

In web development, a session is like a conversation between your browser and a website. It helps the website remember information about you as you move from one page to another. This is essential for things like staying logged in or remembering your preferences.

Key Concepts:

  • Starting a Session: When you visit a website, a session begins. It helps the site keep track of your interactions.
  • Session ID: The browser gets a unique session ID, usually stored as a small file called a cookie. This ID is like your personal ticket, helping the website identify you.
How Do Sessions Work?

Sessions play a key role in making a website feel seamless and personalized for individual users. When a user interacts with a website, a unique session ID is assigned to their browser, usually stored as a cookie.

Here's a simplified overview of how sessions function:

  • Data Storage: The website stores user-specific information, such as preferences or progress, securely on its server. The session ID, carried by the user's browser, acts like a key to access this stored data.

  • Continuity and Experience: Each time the user navigates or performs an action on the website, their session ID is sent along with the request. This allows the website to recognize the user and provide a consistent experience, such as keeping them logged in or remembering their preferred theme.

The importance of sessions lies in their ability to offer a personalized experience, maintain the state of ongoing activities like filling forms or shopping carts, and enhance security by keeping sensitive data on the server rather than the user's device.

Implementing Theme Switching with Sessions

First, let's create and implement a new theme_controller blueprint, which will handle requets to set the theme.

Python
1from flask import Blueprint, redirect, url_for, session 2 3theme_controller = Blueprint('theme', __name__) 4 5@theme_controller.route('/set_theme/<string:theme>', methods=['GET']) 6def set_theme(theme): 7 # Store the theme preference in the session 8 session['theme'] = theme 9 # Redirect back to the ToDo list to apply the new theme 10 return redirect(url_for('todo.list_todos'))

Here's what's happening in theme_controller.py:

  • Route Definition: We define a route /set_theme/<string:theme>, which accepts a theme input (either 'light' or 'dark').
  • Session Assignment: The theme parameter passed to the route is stored in the session using session['theme'] = theme.
  • Redirect: After setting the theme, the user is redirected back to the ToDo list, effectively applying the new theme setting.

Now, let's delve into configuring our Flask application to handle sessions and integrate the theme controller.

Configuring Flask for Session Management

It's important to ensure Flask is properly set up for session management. One key aspect of using sessions securely is setting a secret key. This secret key is utilized by Flask to encrypt the session data, which ensures that user data is protected.

Here's how you configure Flask to handle sessions:

Python
1from flask import Flask 2from controllers.todo_controller import todo_controller 3from controllers.theme_controller import theme_controller 4from middlewares.error_handler import setup_error_handler 5from models import db 6from config import Config 7 8app = Flask(__name__) 9 10app.config.from_object(Config) 11 12# Set a secret key for session management 13app.secret_key = 'your_unique_secret_key' 14 15db.init_app(app) 16 17with app.app_context(): 18 db.create_all() 19 20setup_error_handler(app) 21 22app.register_blueprint(todo_controller) 23 24# Import the new theme controller 25app.register_blueprint(theme_controller) 26 27if __name__ == '__main__': 28 app.run(host='0.0.0.0', port=3000, debug=True)

In this snippet, the app.secret_key line sets up a unique secret key for our Flask application. This is crucial for enabling encrypted session management and should be a complex and secret string in a production environment. With the theme_controller registered, your application is ready to handle theme switching and session management efficiently.

Importance of the Secret Key

The secret key in a Flask application is a critical component used for securing sessions. It acts as a cryptographic key to sign session cookies, ensuring the integrity and confidentiality of the session data. Here's why the secret key is important:

  • Data Integrity: By signing session cookies, the secret key prevents unauthorized modification of the session data by clients. If the session data is tampered with, Flask will reject it as invalid.
  • Confidentiality: The secret key helps encrypt session data, protecting it from being easily read or tampered with by malicious users.
  • Session Invalidation: Changing the secret key will invalidate all existing sessions, causing users to lose their session data and requiring them to log in again. This can be strategically used to force logouts if necessary for security reasons.
  • Security Best Practices: For a production environment, the secret key should be a complex and random string, kept confidential to prevent unauthorized access to session data.

By properly managing the secret key, you ensure that your Flask application maintains a high level of security for user sessions.

Integrating Themes in ToDo Controller

Next, we need to modify our ToDo controller to fetch and apply the theme stored in the session.

Python
1from flask import Blueprint, render_template, request, redirect, url_for, session 2from services.todo_service import TodoService 3 4todo_service = TodoService() 5 6todo_controller = Blueprint('todo', __name__) 7 8@todo_controller.route('/', methods=['GET']) 9def list_todos(): 10 sort_by = request.args.get('sort_by') 11 filter_by = request.args.get('filter_by') 12 todos = todo_service.get_all(sort_by=sort_by, filter_by=filter_by) 13 # Retrieve theme from session or default to 'light' 14 theme = session.get('theme', 'light') 15 # Pass the theme to template 16 return render_template('todo_list.html', todos=todos, theme=theme) 17 18@todo_controller.route('/edit/<int:todo_id>', methods=['GET']) 19def edit_todo(todo_id): 20 todo_item = todo_service.get_by_id(todo_id) 21 if not todo_item: 22 return redirect(url_for('todo.list_todos')) 23 # Retrieve theme from session or default to 'light' 24 theme = session.get('theme', 'light') 25 # Pass the theme to template 26 return render_template('todo_edit.html', todo=todo_item, theme=theme) 27 28# Other routes...

In this snippet from todo_controller.py we update the routes that render our templates:

  • Theme Retrieval: We retrieve the theme from the session using session.get('theme', 'light'). If no theme is set in the session, it defaults to 'light'.
  • Template Rendering: The theme is passed to the todo_list.html and todo_edit.html templates, which will dynamically adjust their styles based on the value of the theme.
Styling the Themes in CSS

Before we look at the HTML template implementation, let's see how we can set different themes in our CSS file located at app/static/styles.css.

CSS
1body.light-theme { 2 font-family: Arial, sans-serif; 3 margin: 10px; 4 color: #1c1c1c; /* Dark text color for contrast */ 5 background-color: #f4f4f4; /* Light background for light mode */ 6} 7 8body.dark-theme { 9 font-family: Arial, sans-serif; 10 margin: 10px; 11 color: #e0e0e0; /* Light text color for contrast */ 12 background-color: #1c1c1c; /* Dark background for dark mode */ 13} 14 15/* Other components without theme... */

In this CSS file, we've defined two different styles for our webpage—one for light mode (light-theme) and one for dark mode (dark-theme).

  • Light Theme (body.light-theme): The text is dark (#1c1c1c) for better readability, and the background is light (#f4f4f4).
  • Dark Theme (body.dark-theme): The text is light (#e0e0e0) so it stands out against the dark background (#1c1c1c).

When our HTML page applies one of these themes, the respective styles are used, making it easy to swap between light and dark modes with just a CSS class change in the HTML's body tag.

Applying Dynamic Theme in HTML Template

Finally, we apply the theme to our HTML templates.

Here, we'll show the implementation with todo_list.html.

HTML, XML
1<!DOCTYPE html> 2<html lang="en"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>Todo List</title> 7 <link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}"> 8</head> 9<!-- Use the given theme in the body --> 10<body class="{{ theme }}-theme"> 11 <h1>Todo List</h1> 12 13 <!-- Option to switch themes --> 14 <form action="{{ url_for('theme.set_theme', theme=('dark' if theme == 'light' else 'light')) }}" method="GET" style="display: inline;"> 15 <button type="submit">Switch Theme</button> 16 </form> 17 18 <!-- Other components... --> 19 20</body> 21</html>

Here's what's happening in todo_list.html:

  • Dynamic Class Application: The body tag's class is set to either light-theme or dark-theme, based on the theme variable from the session. We follow the same approach to implement dynamic theme support in todo_edit.html.
  • Theme Switching: A form is used to toggle the theme by sending a request to the set_theme route. It switches between themes by checking the current theme and setting the opposite.
Summary and Next Steps

In this lesson, you learned how to effectively utilize Flask sessions for managing user-specific preferences, specifically focusing on theme preferences in your ToDo application. By using sessions, you were able to store and retrieve the theme preference across multiple requests, showcasing the core utility of sessions in creating a personalized user experience.

This approach isn't just limited to themes; it lays the groundwork for more complex session-based features, such as user authentication, which you will explore in upcoming lessons. As you move forward, Continue to the practice exercises to reinforce these concepts and solidify your understanding.

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.