惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Stack Overflow Blog
Stack Overflow Blog
WordPress大学
WordPress大学
罗磊的独立博客
S
Secure Thoughts
Schneier on Security
Schneier on Security
博客园 - Franky
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
爱范儿
爱范儿
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Hacker News: Ask HN
Hacker News: Ask HN
PCI Perspectives
PCI Perspectives
Google DeepMind News
Google DeepMind News
S
Security Affairs
SecWiki News
SecWiki News
博客园 - 聂微东
Security Archives - TechRepublic
Security Archives - TechRepublic
Google Online Security Blog
Google Online Security Blog
H
Heimdal Security Blog
S
Security @ Cisco Blogs
Engineering at Meta
Engineering at Meta
C
CXSECURITY Database RSS Feed - CXSecurity.com
Cloudbric
Cloudbric
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
Visual Studio Blog
P
Proofpoint News Feed
Project Zero
Project Zero
T
Threat Research - Cisco Blogs
Webroot Blog
Webroot Blog
Blog — PlanetScale
Blog — PlanetScale
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
W
WeLiveSecurity
Last Week in AI
Last Week in AI
月光博客
月光博客
Microsoft Azure Blog
Microsoft Azure Blog
M
MIT News - Artificial intelligence
有赞技术团队
有赞技术团队
S
Securelist
GbyAI
GbyAI
Application and Cybersecurity Blog
Application and Cybersecurity Blog
C
CERT Recently Published Vulnerability Notes
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Cyberwarzone
Cyberwarzone
B
Blog RSS Feed
P
Palo Alto Networks Blog
H
Hacker News: Front Page
D
Docker
雷峰网
雷峰网
Latest news
Latest news
Microsoft Security Blog
Microsoft Security Blog

Stonecharioteer on Tech

I Traced My Traffic Through a Home Tailscale Exit Node What Was I Reading Last? In Three Not-So-Easy Pieces Dogfooding Is Hard Code blocks in your books, finally GoForGo v0.9.0 Merrilin - We built an app to read books I use a Macbook now Data Structures & Algorithms - Preparing for Interviews Using a local DNS namespace for local service discovery Direction KOllector - Publishing KOReader Highlights gbt: branches touched in the last 24 hours A Soiree into Symbols in Ruby Some Smalltalk about Ruby Loops Ruby Blocks Returning from Ruby Blocks, Procs and Lambdas My Linux Laptop Finally Works: How Claude Helped Me Fix Years of Annoyances TIL: Watchexec - Modern File Watching for Development Workflows A Less Busy Mind GoForGo - Learn Go through live examples Migrating My Old Blog to Hugo with Claude The Qtile Window Manager: A Python-Powered Tiling Experience Read the RFCs that Built the Internet Py-x-Protobuf - Or How I Learned to Stop Worrying and Love Protocol Buffers Python Reverse a List New Beginnings Leaving ChainSafe Systems Screen Lock for Cinnamon Desktop using Zenity and Terminal Commands Crews Not Teams A System for Getting Better at LeetCode So Far So Rust Retrying HTTP Requests with Rust A Primer on Control Charts Learning Rust Explicit is Better than Implicit: Rust for Pythonistas Using Custom Delimiters in Jinja Templates TIL: Creating Fixed Length Iterables in Python Documentation Without Assumption Vagrant Python - A Reflection in 2022 Learning Golang No, A Virtual Machine Is Not Enough: Why Developers Need Native Linux Empathy in Tech For Those Who Came in Late A Weekend With PostgreSQL TIL: Gooey and Python Fire for Quick GUIs and CLIs TIL: 2ality - Dr. Axel Rauschmayer's JavaScript Blog TIL: MassDNS - High-Performance Bulk DNS Lookups TIL: Matomo Analytics, Google Tech Writing, Memory Programming, and NES TV Signals TIL: MontyDB - MongoDB Implemented in Python Returning to the Craft of Programming TIL: CPUFetch, OneFetch, and Learn CSS TIL: DNS Performance Testing and Pi-hole with Unbound TIL: Eli Bendersky's Blog, Awesome By Example, NoCoDB, and Martin Kleppmann TIL: CRDTs, Extreme HTTP Performance, and BYTEPATH Game TIL: AutoInvent, ASGI, Python Packaging, RAPIDS GPU Computing, and FlaskCon TIL: MangaDesk - Terminal Client for MangaDex TIL: McFly - Smart Shell History Search TIL: Siege Load Testing and Awesome FastAPI Resources TIL: Ventoy Bootable USB and Justniffer Network Analysis TIL: CLI Code Review, Git Split Diffs, and Internal Combustion Engine TIL: Benford's Law, Web Security Headers, Event Sourcing, and Mozilla Security Guidelines How to Write Documentation - The README.md File The Importance of Documentation TIL: NNgroup UX Research, SponsorBlock, and Labella Python Library TIL: The Little Book of Rust Macros and Rust Performance Book TIL: Git-Bug Distributed Issue Tracker and Omni Kubernetes Monitoring TIL: Zellij - Modern Terminal Multiplexer TIL: How Discord Handles 2.5 Million Concurrent Voice Users TIL: Volumio - The Audiophile Music Player TIL: Areopagitica - Milton's Defense of Free Speech TIL: Fast Node Manager, Zoxide Smart CD, Technical Writing, PyO3, and Qubes OS TIL: Slurm Workload Manager for HPC Clusters TIL: Data Visualization Guide and Oso Authorization Academy TIL: CORS Deep Dive, Piku Tiny PaaS, Rust Strings, and Deno Standard Library TIL: Raspberry Pi OS Development, Vim Beginner Guide, Password Management, and QueryBook TIL: uBlock Origin Performance Optimization on Firefox TIL: Breaking PostgreSQL at Scale and LeetCode Problem Patterns TIL: Awesome Tmux Resources for Terminal Multiplexing TIL: Grit - A Multitree-Based Personal Task Manager TIL: Lens 4.2 Kubernetes IDE, Shell Scripting Guide, and Dark HTTP Server Do The Job You Hate So You Won't Hate The Job You Love TIL: Innernet VPN Solution and NoteCalc Calculator App TIL: Argo CD for GitOps and Lens Kubernetes IDE TIL: Modern Rust CLI Tools - System Monitoring, HTTP Requests, and DNS TIL: tz - A Time Zone Helper Tool TIL: Distributed Systems Education, Fallacies, and Self-Hosted Internet Archiving TIL: Real-Time Voice Cloning Technology TIL: ChartMuseum for Helm, AMD's Corporate Journey, and Kubernetes Pod Scaling TIL: Docker and Kubernetes Tools - Whaler, Descheduler, and Dive TIL: Post-Mortem Collection, Terminal Plotting, and Technical Twitter TIL: Dark Mode Toggle Web Component by Google Chrome Labs TIL: Python eval(), exec(), and compile() Functions TIL: Camelot PDF Tables, PostgreSQL Row Level Security, Zerodha Varsity, and Write Yourself a Git TIL: fuser Command for Process and File Investigation TIL: i Hate Regex - The Ultimate Regex Cheat Sheet TIL: Dolt - Git for Data and Database Version Control TIL: x86 Assembly Programming and SafeEyes Break Reminder TIL: Comprehensive Distributed Systems Reading List TIL: Cosmopolitan C Library, Distributed Systems Book, High Performance Browser Networking, and Rust Roguelike Tutorial
TIL: Flask Advanced Patterns and Development Tools
2020-07-15 · via Stonecharioteer on Tech

Today I delved deep into advanced Flask patterns and discovered several powerful features and tools that can significantly improve Flask application development and maintainability.

Flask Method Views - Better Organization

Flask’s Method Views provide a cleaner way to organize complex endpoints by grouping related functionality into classes:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from flask import Flask, request, render_template
from flask.views import MethodView

app = Flask(__name__)

class UserAPI(MethodView):
    def get(self, user_id):
        if user_id is None:
            # Return list of users
            return self.list_users()
        else:
            # Return specific user
            return self.get_user(user_id)

    def post(self):
        # Create new user
        return self.create_user()

    def put(self, user_id):
        # Update existing user
        return self.update_user(user_id)

    def delete(self, user_id):
        # Delete user
        return self.delete_user(user_id)

    def list_users(self):
        # Implementation for listing users
        return {"users": []}

    def get_user(self, user_id):
        # Implementation for getting specific user
        return {"user": {"id": user_id}}

# Register the view
user_view = UserAPI.as_view('user_api')
app.add_url_rule('/users/', defaults={'user_id': None},
                 view_func=user_view, methods=['GET',])
app.add_url_rule('/users/', view_func=user_view, methods=['POST',])
app.add_url_rule('/users/<int:user_id>', view_func=user_view,
                 methods=['GET', 'PUT', 'DELETE'])

When to Use Method Views

Method Views are particularly beneficial when:

  • You have complex endpoints with multiple HTTP methods
  • Related functionality is scattered across multiple functions
  • You want to share state or helper methods between endpoints
  • You’re building RESTful APIs with consistent patterns

Flask Signals - Decoupled Communication

Flask Signals use the Blinker library to enable decoupled communication between different parts of your application:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from flask import Flask
from flask.signals import Namespace

app = Flask(__name__)
my_signals = Namespace()

# Define custom signals
user_logged_in = my_signals.signal('user-logged-in')
order_placed = my_signals.signal('order-placed')

# Signal handlers
@user_logged_in.connect
def log_user_activity(sender, user=None, **extra):
    print(f"User {user.username} logged in")
    # Update last login time
    # Send welcome email
    # Log analytics event

@order_placed.connect
def process_order(sender, order=None, **extra):
    print(f"Processing order {order.id}")
    # Send confirmation email
    # Update inventory
    # Trigger fulfillment

# Using built-in Flask signals
from flask import request_started, request_finished

@request_started.connect
def log_request_start(sender, **extra):
    print(f"Request started: {request.endpoint}")

@request_finished.connect
def log_request_end(sender, response=None, **extra):
    print(f"Request finished with status: {response.status_code}")

# Emit custom signals
@app.route('/login', methods=['POST'])
def login():
    # ... authentication logic ...
    user_logged_in.send(app._get_current_object(), user=current_user)
    return "Logged in successfully"

Available Flask Signals

Built-in Flask Signals

  • request_started - Before request processing begins
  • request_finished - After response is sent
  • request_tearing_down - During request teardown
  • got_request_exception - When an unhandled exception occurs
  • template_rendered - After template is rendered
  • before_render_template - Before template rendering

Advanced Flask Profiling

Werkzeug Profiler Middleware

Here’s a comprehensive profiling setup for Flask applications:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from werkzeug.contrib.profiler import ProfilerMiddleware
from flask import Flask, request
import os

app = Flask(__name__)

class ConditionalProfilerMiddleware:
    def __init__(self, app, restrictions=None, profile_dir=None):
        self.app = app
        self.restrictions = restrictions or [30]
        self.profile_dir = profile_dir or './profiles'

        # Create profile directory if it doesn't exist
        os.makedirs(self.profile_dir, exist_ok=True)

    def __call__(self, environ, start_response):
        # Only profile if requested
        if environ.get('HTTP_X_PROFILE'):
            profiler = ProfilerMiddleware(
                self.app,
                restrictions=self.restrictions,
                profile_dir=self.profile_dir
            )
            return profiler(environ, start_response)
        return self.app(environ, start_response)

# Apply conditional profiling
app.wsgi_app = ConditionalProfilerMiddleware(
    app.wsgi_app,
    restrictions=[30]  # Show top 30 function calls
)

@app.route('/heavy-computation')
def heavy_computation():
    # Simulate expensive operation
    result = sum(i * i for i in range(100000))
    return f"Result: {result}"

# Usage: Send requests with X-Profile header
# curl -H "X-Profile: 1" http://localhost:5000/heavy-computation

Custom Performance Decorators

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import time
import functools
from flask import current_app

def profile_endpoint(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()

        duration = end_time - start_time
        current_app.logger.info(
            f"Endpoint {func.__name__} took {duration:.4f} seconds"
        )

        # Log slow requests
        if duration > 1.0:
            current_app.logger.warning(
                f"Slow endpoint detected: {func.__name__} ({duration:.4f}s)"
            )

        return result
    return wrapper

@app.route('/api/data')
@profile_endpoint
def get_data():
    # Your endpoint logic here
    return {"data": "response"}

Flask Security Extensions

Flask-Security-Too

Flask-Security-Too provides comprehensive security patterns for Flask applications:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from flask import Flask
from flask_security import Security, SQLAlchemyUserDatastore
from flask_security import UserMixin, RoleMixin, login_required

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'
app.config['SECURITY_PASSWORD_SALT'] = 'your-password-salt'

# Setup Flask-Security
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)

# Features included:
# - User registration and authentication
# - Role-based access control
# - Password hashing with salt
# - Session management
# - Two-factor authentication
# - Password recovery
# - Email confirmation

@app.route('/protected')
@login_required
def protected_view():
    return "This is a protected view"

Flask-Security-Too Features

  • Authentication: Login, logout, registration
  • Authorization: Role and permission-based access
  • Password Security: Secure hashing and validation
  • Session Management: Secure session handling
  • Two-Factor Auth: Optional 2FA support
  • Email Integration: Confirmation and recovery emails
  • Customizable: Extensive configuration options

Flask Testing and Mocking Best Practices

Proper Mocking in Flask Tests

A crucial testing insight I learned: When mocking Python functions in Flask tests, reference the module where the function is called, not where it originates:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# api/users.py
from services.email import send_welcome_email

def create_user(username, email):
    user = User(username=username, email=email)
    db.session.add(user)
    db.session.commit()

    # Function is called here
    send_welcome_email(user.email)
    return user

# tests/test_users.py
import pytest
from unittest.mock import patch

class TestUserCreation:
    @patch('api.users.send_welcome_email')  # Mock where it's CALLED
    def test_create_user_sends_email(self, mock_send_email):
        # NOT: @patch('services.email.send_welcome_email')
        # That would be where it's DEFINED, not where it's CALLED

        user = create_user('testuser', '[email protected]')

        assert user.username == 'testuser'
        mock_send_email.assert_called_once_with('[email protected]')

Common Mocking Mistake

Many developers patch the module where a function is defined rather than where it’s imported and called. This leads to mocks that don’t work because the test patches the wrong reference.

Wrong: @patch('services.email.send_welcome_email')
Right: @patch('api.users.send_welcome_email')

Custom Error Handlers

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from flask import jsonify
from werkzeug.exceptions import HTTPException

@app.errorhandler(404)
def not_found(error):
    return jsonify({
        'error': 'Not found',
        'message': 'The requested resource was not found',
        'status_code': 404
    }), 404

@app.errorhandler(500)
def internal_error(error):
    db.session.rollback()
    return jsonify({
        'error': 'Internal server error',
        'message': 'An unexpected error occurred',
        'status_code': 500
    }), 500

@app.errorhandler(HTTPException)
def handle_http_exception(error):
    return jsonify({
        'error': error.name,
        'message': error.description,
        'status_code': error.code
    }), error.code

Request Context Processors

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@app.context_processor
def inject_user():
    return dict(current_user=get_current_user())

@app.context_processor
def inject_config():
    return dict(
        app_name=app.config.get('APP_NAME'),
        version=app.config.get('VERSION')
    )

# Now available in all templates
# {{ current_user.username }}
# {{ app_name }} v{{ version }}

Flask Shell Context

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@app.shell_context_processor
def make_shell_context():
    return {
        'db': db,
        'User': User,
        'Post': Post,
        'create_user': lambda u, e: User(username=u, email=e)
    }

# Now available in `flask shell`:
# >>> user = create_user('john', '[email protected]')
# >>> db.session.add(user)
# >>> db.session.commit()

Custom CLI Commands

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import click

@app.cli.command()
def init_db():
    """Initialize the database."""
    db.create_all()
    click.echo('Database initialized.')

@app.cli.command()
@click.argument('username')
@click.argument('email')
def create_admin(username, email):
    """Create an admin user."""
    admin = User(username=username, email=email, is_admin=True)
    db.session.add(admin)
    db.session.commit()
    click.echo(f'Admin user {username} created.')

# Usage:
# flask init-db
# flask create-admin admin [email protected]

Key Takeaways

Architecture Benefits

  1. Method Views: Organize complex endpoints more maintainably
  2. Signals: Enable loose coupling between application components
  3. Security Extensions: Don’t reinvent authentication and authorization
  4. Proper Testing: Mock at the right level for reliable tests

Performance Insights

  1. Conditional Profiling: Only profile when needed to avoid overhead
  2. Custom Metrics: Track application-specific performance indicators
  3. Middleware Patterns: Implement cross-cutting concerns cleanly
  4. Database Optimization: Profile database queries specifically

Development Workflow

  1. CLI Commands: Automate common development tasks
  2. Shell Context: Make debugging and exploration easier
  3. Error Handling: Provide consistent, informative error responses
  4. Context Processors: Share common data across templates

Flask Philosophy

Flask’s power lies not just in its simplicity, but in its extensibility. These advanced patterns show how Flask scales from simple apps to complex, enterprise-grade applications while maintaining clarity and control.

This exploration of advanced Flask patterns demonstrates that while Flask starts simple, it provides sophisticated tools for building robust, maintainable web applications when you need them.


These insights from my learning archive showcase Flask’s evolution from a micro-framework to a comprehensive platform for building scalable web applications with proper architecture and security patterns.