Я хочу создать пользовательскую функцию path
в Django 3, которая поддерживает применение декоратора к шаблону URL. Я вижу этот источник в GitHub и попробуйте обновить его до Django 3. это мои обновленные коды:
from functools import partial
from django.core.exceptions import ImproperlyConfigured
from django.urls.resolvers import RegexPattern, RoutePattern
from django.utils.encoding import force_text
import six
from django.urls import ResolverMatch, Resolver404, get_callable, URLResolver, URLPattern
class DecorateURLResolver(URLResolver):
def __init__(self, pattern, urlconf_name, default_kwargs=None, app_name=None, namespace=None, wrap=None):
super(DecorateURLResolver, self).__init__(pattern, urlconf_name, default_kwargs, app_name, namespace)
if isinstance(wrap, (tuple, list)):
self.wrap = wrap
elif wrap:
self.wrap = [wrap]
else:
self.wrap = []
def resolve(self, path):
path = str(path) # path may be a reverse_lazy object
tried = []
match = self.pattern.match(path)
if match:
new_path, args, kwargs = match
for pattern in self.url_patterns:
try:
sub_match = pattern.resolve(new_path)
except Resolver404 as e:
sub_tried = e.args[0].get('tried')
if sub_tried is not None:
tried.extend([pattern] + t for t in sub_tried)
else:
tried.append([pattern])
else:
if sub_match:
# Merge captured arguments in match with submatch
sub_match_dict = {**kwargs, **self.default_kwargs}
# Update the sub_match_dict with the kwargs from the sub_match.
sub_match_dict.update(sub_match.kwargs)
# If there are *any* named groups, ignore all non-named groups.
# Otherwise, pass all non-named arguments as positional arguments.
sub_match_args = sub_match.args
if not sub_match_dict:
sub_match_args = args + sub_match.args
current_route = '' if isinstance(pattern, URLPattern) else str(pattern.pattern)
return ResolverMatch(
sub_match.func,
sub_match_args,
sub_match_dict,
sub_match.url_name,
[self.app_name] + sub_match.app_names,
[self.namespace] + sub_match.namespaces,
self._join_route(current_route, sub_match.route),
)
tried.append([pattern])
raise Resolver404({'tried': tried, 'path': new_path})
raise Resolver404({'path': path})
def _decorate(self, callback):
for decorator in reversed(self.wrap):
callback = decorator(callback)
return callback
class DecorateURLPattern(URLPattern):
def __init__(self, pattern, callback, default_args=None, name=None, wrap=None):
super(DecorateURLPattern, self).__init__(pattern, callback, default_args, name)
if isinstance(wrap, (tuple, list)):
self.wrap = wrap
elif wrap:
self.wrap = [wrap]
else:
self.wrap = []
@property
def callback(self):
if self._callback is not None:
return self._decorate(self._callback)
self._callback = get_callable(self._callback_str)
return self._decorate(self._callback)
def _decorate(self, callback):
for decorator in reversed(self.wrap):
callback = decorator(callback)
return callback
def _custom_path(route, view, kwargs=None, name=None, Pattern=None, wrap=None):
if isinstance(view, (list, tuple)):
# For include(...) processing.
pattern = Pattern(route, is_endpoint=False)
urlconf_module, app_name, namespace = view
return DecorateURLResolver(
pattern,
urlconf_module,
kwargs,
app_name=app_name,
namespace=namespace,
wrap=wrap,
)
elif callable(view):
pattern = Pattern(route, name=name, is_endpoint=True)
return DecorateURLPattern(pattern, view, kwargs, name, wrap)
else:
raise TypeError('view must be a callable or a list/tuple in the case of include().')
custom_path = partial(_custom_path, Pattern=RoutePattern)
re_custom_path = partial(_custom_path, Pattern=RegexPattern)
Но это не работает и выдает эту ошибку:
self.callback = callback # the view AttributeError: can't set attribute
пожалуйста, помогите мне обновить этот исходный код до Django 3.