data_capture/decorators.py

Summary

Maintainability
A
3 hrs
Test Coverage
A
100%
from functools import wraps

from django.shortcuts import redirect

from frontend import ajaxform


def handle_cancel(*args, redirect_name='index', key_prefix='data_capture:'):
    '''
    Decorator to handle cancel behavior in Data Capture flows.
    The associated request's POST data is checked for a 'cancel' key,
    and, if found, all session keys that start with `key_prefix`
    are deleted and the request is redirected to `redirect_name`.
    '''

    no_args = False
    if len(args) == 1 and callable(args[0]):
        # We were called without args
        function = args[0]
        no_args = True

    def decorator(function):
        @wraps(function)
        def wrapper(request, *args, **kwargs):
            if request.method == 'POST' and 'cancel' in request.POST:
                if key_prefix:
                    # .keys() returns an iterator, which can't be deleted from
                    # while in a loop, so we use list() to get an actual list
                    session_keys = list(request.session.keys())
                    for k in session_keys:
                        if k.startswith(key_prefix):
                            del request.session[k]

                # if AJAX request, then send JSON response
                # that has a 'redirect_url' property
                if request.is_ajax():
                    return ajaxform.ajax_redirect(redirect_name)

                # redirect to the view named redirect_name
                return redirect(redirect_name)

            else:
                # pass through
                return function(request, *args, **kwargs)

        return wrapper

    if no_args:
        return decorator(function)
    else:
        return decorator