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

View

Base class for Duck views.

Functions

cached_view

Decorator for caching view outputs based on selected request attributes or computed callable results.

csrf_exempt

Decorator that marks a view as exempt from CSRF middleware checks.

Data

DEFAULT_VIEW_CACHE

API

duck.views.DEFAULT_VIEW_CACHE

‘InMemoryCache(…)’

exception duck.views.SkipViewCaching[source]

Bases: Exception

This 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 ID but the USER ID is unknown or invalid, user can just raise SkipViewCaching exception 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)[source]

Base class for Duck views.

Subclasses override run(self, request, **kwargs) to handle the request. The signature is fixed so views compose cleanly with decorators like login_required.

Initialization

Initialize the view.

Parameters:
  • request – The incoming HTTP request.

  • **kwargs – Parameters extracted from the matched route.

async async_dispatch() Any[source]

Asynchronously dispatch the view using its current request and route parameters.

Returns:

The value returned by run().

Return type:

Any

dispatch() Any[source]

Dispatch the view using its current request and route parameters.

Returns:

The value returned by run().

Return type:

Any

abstractmethod run(request: duck.http.request.HttpRequest, **kwargs) Optional[duck.http.response.HttpResponse][source]

Handle the request.

Subclasses must override this method.

Parameters:
  • request – The incoming HTTP request.

  • **kwargs – Parameters extracted from the matched route.

Returns:

The response generated by the view.

Return type:

Optional[HttpResponse]

exception duck.views.ViewCachingError[source]

Bases: Exception

Raised when the cached_view decorator fails.

Initialization

Initialize self. See help(type(self)) for accurate signature.

exception duck.views.ViewCachingWarning[source]

Bases: UserWarning

Warning 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)[source]

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, including View.run methods.

  • 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.

  • namespace

    Optional string or callable returning a namespace prefix for keys. Use namespace for grouping and easy bulk 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). Defaults to skip_cache, meaning if request.skip_cache=True then caching is skipped for that request.

  • on_cache_result – Callable executed upon receiving a result from cache. Use this if some data needs to be reinitialized.

  • returns_static_response – By default, caching a view that returns a component or component response while LivelyComponentSystem is active and not disabled on the target component may raise ViewCachingWarning. Setting this to True tells the system the component is static and safe from direct user-specific alteration, avoiding the warning.

  • freeze_if_component_response – Whether to freeze the target component if the result is a component/component response. Boosts performance by >=50%, and only applies if returns_static_response=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, request, **kwargs):
        # 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, and on View.run methods.

  • 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 = True will bypass caching.

  • For callable targets, if caching can no longer proceed, e.g. some data is unavailable, raise SkipViewCaching to tell the caching system that caching is not possible for this request.

duck.views.csrf_exempt(view_func)[source]

Decorator that marks a view as exempt from CSRF middleware checks.

Usage: @csrf_exempt def my_view(request): …

@csrf_exempt
async def my_async_view(request):
    ...