python
44 lines · 8 steps
A parameterized query-param decorator in Flask
A decorator factory validates and casts query-string parameters before a Flask view ever runs.
Explained by
highlit
1from functools import wraps
2from flask import request, jsonify
3
4
5def query_params(*required, **optional):
6 def decorator(view):
7 @wraps(view)
8 def wrapper(*args, **kwargs):
9 parsed = {}
10 missing = [name for name in required if name not in request.args]
11 if missing:
12 return jsonify(error="missing required parameters", params=missing), 400
13
14 for name in required:
15 parsed[name] = request.args[name]
16
17 for name, caster in optional.items():
18 raw = request.args.get(name)
19 if raw is None:
20 parsed[name] = None
21 continue
22 try:
23 parsed[name] = caster(raw) if callable(caster) else raw
24 except (ValueError, TypeError):
25 return jsonify(error=f"invalid value for '{name}'", value=raw), 400
26
27 kwargs["params"] = parsed
28 return view(*args, **kwargs)
29
30 return wrapper
31
32 return decorator
33
34
35@app.route("/reports")
36@query_params("account_id", page=int, per_page=int, active=lambda v: v.lower() == "true")
37def list_reports(params):
38 page = params["page"] or 1
39 per_page = params["per_page"] or 25
40 query = Report.query.filter_by(account_id=params["account_id"])
41 if params["active"] is not None:
42 query = query.filter_by(active=params["active"])
43 reports = query.paginate(page=page, per_page=per_page)
44 return jsonify(items=[r.to_dict() for r in reports.items], total=reports.total)
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1A decorator factory takes arguments and returns the actual decorator, letting one wrapper adapt to per-route rules.
- 2Centralizing parameter validation keeps view functions focused on business logic instead of request parsing.
- 3Returning early with a 400 on bad input guarantees the view only runs with clean, typed data.
Related explainers
python
from fastapi import FastAPI, WebSocket, WebSocketDisconnect app = FastAPI()
Building a WebSocket chat with FastAPI
websockets
broadcast
connection-management
Intermediate
9 steps
php
<?php namespace App\Services\Checkout;
Validating coupons with Laravel's Pipeline
pipeline
chain of responsibility
transactions
Intermediate
7 steps
python
import time import uuid from django.utils.deprecation import MiddlewareMixin
Attaching per-request context in Django
middleware
request lifecycle
multi-tenancy
Intermediate
7 steps
javascript
function evaluate(expression) { const tokens = tokenize(expression); let pos = 0;
Building a recursive descent calculator
parsing
recursion
operator-precedence
Intermediate
8 steps
php
<?php namespace App\Services;
How a password strength validator works in PHP
validation
regular-expressions
data-driven
Intermediate
8 steps
python
import random from typing import Iterator, List
How reservoir sampling picks k items
reservoir-sampling
streaming
randomness
Intermediate
5 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/a-parameterized-query-param-decorator-in-flask-explained-python-c8ec/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.