duck.views¶
Duck view system.
This module defines the base View class, which serves as the foundation
for handling HTTP requests in the Duck web framework. Views process incoming
HttpRequest objects and return HttpResponse objects.
Developers can subclass View to define custom request handling logic by
overriding the run() method. This abstraction allows separation of business
logic from routing and middleware.
Module Contents¶
Classes¶
Base class for Duck views (request handlers). |
Functions¶
Decorator for caching view outputs based on selected request attributes or computed callable results. |
Data¶
API¶
- duck.views.DEFAULT_VIEW_CACHE¶
‘InMemoryCache(…)’
- exception duck.views.SkipViewCaching¶
Bases:
ExceptionThis is not an error as such but it’s just an interrupt for telling us that caching cannot proceed. This is usually when some data cannot be satisfied or some data is unavailable or broken.
Example:
Lets say user wants to cache views based on
USER IDbut the USER ID is unknown or invalid, user can just raiseSkipViewCachingexception to tell the system that caching is nolonger possible.
Initialization
Initialize self. See help(type(self)) for accurate signature.
- class duck.views.View(request: duck.http.request.HttpRequest, **kwargs)¶
Base class for Duck views (request handlers).
A view encapsulates logic to handle an HTTP request and produce a response. Views are instantiated per request and can carry state during request processing.
Subclasses should override the
run()method to implement custom behavior.- Variables:
request – The incoming HTTP request object.
kwargs – Additional parameters extracted from the route (e.g., path variables).
Initialization
Initializes the view with the incoming request and any route parameters.
- Parameters:
request – The HTTP request to be handled.
**kwargs – Arbitrary keyword arguments passed from the URL routing, such as path variables.
- abstractmethod run() Optional[duck.http.response.HttpResponse]¶
Handles the request and returns an HTTP response.
This method should be overridden by subclasses to implement custom request handling logic. It must return an
HttpResponseobject to be sent to the client.If no response is expected (e.g., in cases of low-level socket handling), raise
duck.exceptions.all.ExpectingNoResponseand handle the response manually usingrequest.client_socketandrequest.client_address.- Returns:
The HTTP response or data that can be converted to HTTP response to be returned to the client.
- Return type:
Optional[HttpResponse]
- Raises:
NotImplementedError – If the method is not overridden in a subclass.
- strictly_async() bool¶
Indicates whether the view requires asynchronous execution.
This is useful in environments like WSGI, where strictly asynchronous views should be deferred to an async execution queue instead of being executed synchronously.
Override this method if your view contains non-blocking I/O or requires an event loop context.
- Returns:
True if the view should be treated as strictly async, False otherwise.
- Return type:
bool
- exception duck.views.ViewCachingError¶
Bases:
ExceptionRaised when the cached_view decorator fails.
Initialization
Initialize self. See help(type(self)) for accurate signature.
- exception duck.views.ViewCachingWarning¶
Bases:
UserWarningWarning that will be logged if user tries to cache a view which might cause issues.
Initialization
Initialize self. See help(type(self)) for accurate signature.
- duck.views.cached_view(targets: Union[Dict[Union[str, Callable], Dict[str, Any]], List[str]], expiry: Optional[float] = None, cache_backend: Optional = None, namespace: Optional[Union[str, Callable]] = None, skip_cache_attr: str = 'skip_cache', on_cache_result: Optional[Callable] = None, returns_static_response: bool = False, freeze_if_component_response: bool = True)¶
Decorator for caching view outputs based on selected request attributes or computed callable results.
This decorator supports:
Direct request attribute extraction.
Callable attributes on the request (with dynamic args/kwargs).
External Python callables used as cache-key producers.
Sync and async view handlers.
Sync/async cache backends with automatic compatibility conversion.
The caching system guarantees stable, deterministic cache keys by converting all target values into a normalized (and hashable) structure.
- Parameters:
targets –
Defines which request attributes or computed callable results should contribute to the cache key.
List[str]: Direct request attribute lookups. Example: [“path”, “method”]
Dict[str or Callable, Dict[str, Any]]: Complex targets supporting: { “<request_attr_or_callable>”: {“args”: (…), “kwargs”: {…}} } { my_function: {“args”: (…), “kwargs”: {…}} }
Dynamic formatting is supported: “{request.path}” → replaced at runtime.
expiry – TTL/expiry in seconds. If None, backend default TTL is used.
cache_backend – A cache backend implementing: get(key) set(key, value, ttl) Async backends or sync backends are both supported.
(Optional[Union[str (namespace) –
Optional string or callable returning a namespace prefix for keys. Use
namespacefor grouping and easy bulky cache invalidation.Example:
@cached_view(targets=['path'], namespace=lambda request: request.COOKIES.get('user_id')) def handler(request): # Caches based on USER ID instead of global caching. return HttpResponse("OK")Callable]] –
Optional string or callable returning a namespace prefix for keys. Use
namespacefor grouping and easy bulky cache invalidation.Example:
@cached_view(targets=['path'], namespace=lambda request: request.COOKIES.get('user_id')) def handler(request): # Caches based on USER ID instead of global caching. return HttpResponse("OK")skip_cache_attr – Optional request attribute to skip caching (for debugging). This defaults to
skip_cache, meaning, ifrequest.skip_cache=Truethen, cache is skipped for that request.on_cache_result – This is a callable that can be executed upon receiving a result from cache. If some data needs to be reinitialized, you can do this here.
returns_static_response – By default, If user tries to cache a view which returns either a component or component response whilst
LivelyComponentSystemis active and is not disabled on the target component. This may lead toViewCachingWarningbeing raised. This tells the system that the component is a static component and cannot be altered directly by users. So setting this to True avoidsViewCachingWarningbeing logged on safe static components. In the future, this will apply to any dynamic responses.freeze_if_component_response – Whether to freeze target component if the result is a component/component response. This boosts performance by
>=50%and it only applies ifreturns_static_component=True.
- Returns:
Wrapped view function with caching behavior.
- Return type:
Callable
- Raises:
ViewCachingError – Malformed target configuration, formatting errors, missing attributes, or errors inside computed callables.
Example:
from duck.views import View from duck.utils.performance import exec_time @cached_view(targets=["path"]) def handler(request): # View that will be cached based on request's path only.' return HttpResponse("OK") class myView(View): @cached_view(targets=["fullpath", "method"]) async def run(self): # View that will be cached based on request's path plus method. return HttpResponse("OK") exec(handler)() # Slow for the first time, prints more time exec_time(handler)() # Fast, prints less time. # Complex caching @cached_view(targets={"callable_request_attribute": {'args': "{request.path}"}) def handler_2(request): # View is cached based on request callable attribute. return HttpResponse("OK") @cached_view(targets={my_custom_function: {'args': "{request.path}"}) def handler_3(request): # View cached based on custom external function. return HttpResponse("OK")Notes:
Dynamic formatting (“{request.path}”) is supported everywhere.
Cache keys use stable frozenset+tuple structures for high hashing performance.
Custom callables receive: (request, *view_args, *resolved_args, **view_kwargs, **resolved_kwargs)
Works transparently on both synchronous and asynchronous views.
Sync cache backends are auto-wrapped for async views; async backends are auto-wrapped for sync views.
Callable targets may raise errors at runtime; these are wrapped into ViewCachingError.
When Lively Component System is active, caching Component or ComponentResponse will issue a safety warning to avoid state leakage across users.
targets=[] is not allowed — caching requires at least one dimension of variation.
Namespace allows per-user, per-tenant, or per-feature cache isolation.
Setting
request.skip_cache = Truewill bypass caching.For callable targets, if caching can nolonger be possible e.g. some data you might wanna use is unavailable, exception
SkipViewCachingcan be raised to tell the caching system that caching is not possible because of some data invalidity.