Ticket #13409: wrap_kwarg_for_url.patch

File wrap_kwarg_for_url.patch, 4.8 KB (added by Florian Sening, 13 years ago)

New feature: wrap kwarg for "url" to decorate views. (usable with trunk)

  • conf/urls/defaults.py

     
    2727        pattern_list.append(t)
    2828    return pattern_list
    2929
    30 def url(regex, view, kwargs=None, name=None, prefix=''):
     30def url(regex, view, kwargs=None, name=None, prefix='', wrap=None):
    3131    if isinstance(view, (list,tuple)):
    3232        # For include(...) processing.
    3333        urlconf_module, app_name, namespace = view
    34         return RegexURLResolver(regex, urlconf_module, kwargs, app_name=app_name, namespace=namespace)
     34        return RegexURLResolver(regex, urlconf_module, kwargs, app_name=app_name, namespace=namespace, wrap=wrap)
    3535    else:
    3636        if isinstance(view, basestring):
    3737            if not view:
    3838                raise ImproperlyConfigured('Empty URL pattern view name not permitted (for pattern %r)' % regex)
    3939            if prefix:
    4040                view = prefix + '.' + view
    41         return RegexURLPattern(regex, view, kwargs, name)
     41        return RegexURLPattern(regex, view, kwargs, name, wrap=wrap)
    4242
  • core/urlresolvers.py

     
    116116    return callback[:dot], callback[dot+1:]
    117117
    118118class RegexURLPattern(object):
    119     def __init__(self, regex, callback, default_args=None, name=None):
     119    def __init__(self, regex, callback, default_args=None, name=None, wrap=None):
    120120        # regex is a string representing a regular expression.
    121121        # callback is either a string like 'foo.views.news.stories.story_detail'
    122122        # which represents the path to a module and a view function name, or a
     
    129129            self._callback_str = callback
    130130        self.default_args = default_args or {}
    131131        self.name = name
     132        if isinstance(wrap, (list, tuple)):
     133            self.wrap = wrap
     134        elif wrap:
     135            self.wrap = [wrap]
     136        else:
     137            self.wrap = []
    132138
    133139    def __repr__(self):
    134140        return smart_str(u'<%s %s %s>' % (self.__class__.__name__, self.name, self.regex.pattern))
     
    159165
    160166    def _get_callback(self):
    161167        if self._callback is not None:
    162             return self._callback
     168            return self._decorate(self._callback)
    163169        try:
    164170            self._callback = get_callable(self._callback_str)
    165171        except ImportError, e:
     
    168174        except AttributeError, e:
    169175            mod_name, func_name = get_mod_func(self._callback_str)
    170176            raise ViewDoesNotExist("Tried %s in module %s. Error was: %s" % (func_name, mod_name, str(e)))
    171         return self._callback
     177        return self._decorate(self._callback)
    172178    callback = property(_get_callback)
    173179
     180    def _decorate(self, callback):
     181        for decorator in reversed(self.wrap):
     182            callback = decorator(callback)
     183        return callback
     184
    174185class RegexURLResolver(object):
    175     def __init__(self, regex, urlconf_name, default_kwargs=None, app_name=None, namespace=None):
     186    def __init__(self, regex, urlconf_name, default_kwargs=None, app_name=None, namespace=None, wrap=None):
    176187        # regex is a string representing a regular expression.
    177188        # urlconf_name is a string representing the module containing URLconfs.
    178189        self.regex = re.compile(regex, re.UNICODE)
     
    186197        self._reverse_dict = None
    187198        self._namespace_dict = None
    188199        self._app_dict = None
     200        if isinstance(wrap, (tuple, list)):
     201            self.wrap = wrap
     202        elif wrap:
     203            self.wrap = [wrap]
     204        else:
     205            self.wrap = []
    189206
    190207    def __repr__(self):
    191208        return smart_str(u'<%s %s (%s:%s) %s>' % (self.__class__.__name__, self.urlconf_name, self.app_name, self.namespace, self.regex.pattern))
     
    262279                        sub_match_dict.update(self.default_kwargs)
    263280                        for k, v in sub_match.kwargs.iteritems():
    264281                            sub_match_dict[smart_str(k)] = v
    265                         return ResolverMatch(sub_match.func, sub_match.args, sub_match_dict, sub_match.url_name, self.app_name or sub_match.app_name, [self.namespace] + sub_match.namespaces)
     282                        return ResolverMatch(self._decorate(sub_match.func), sub_match.args, sub_match_dict, sub_match.url_name, self.app_name or sub_match.app_name, [self.namespace] + sub_match.namespaces)
    266283                    tried.append([pattern])
    267284            raise Resolver404({'tried': tried, 'path': new_path})
    268285        raise Resolver404({'path' : path})
    269286
     287    def _decorate(self, callback):
     288        for decorator in reversed(self.wrap):
     289            callback = decorator(callback)
     290        return callback
     291
    270292    def _get_urlconf_module(self):
    271293        try:
    272294            return self._urlconf_module
Back to Top