码迷,mamicode.com
首页 > Web开发 > 详细

Django源码分析——urlresolvers.py

时间:2015-09-06 19:52:56      阅读:317      评论:0      收藏:0      [点我收藏+]

标签:

因为看URL,所以跟到了urlresolvers.py

regex是正则表达式

view

kwargs

name 就是那个 name=‘blog‘

prefix

  1 class RegexURLResolver(LocaleRegexProvider):
  2     def __init__(self, regex, urlconf_name, default_kwargs=None, app_name=None, namespace=None):
  3         LocaleRegexProvider.__init__(self, regex)
  4         # urlconf_name is a string representing the module containing URLconfs.
  5         self.urlconf_name = urlconf_name
  6         if not isinstance(urlconf_name, six.string_types):
  7             self._urlconf_module = self.urlconf_name
  8         self.callback = None
  9         self.default_kwargs = default_kwargs or {}
 10         self.namespace = namespace
 11         self.app_name = app_name
 12         self._reverse_dict = {}
 13         self._namespace_dict = {}
 14         self._app_dict = {}
 15 
 16     def __repr__(self):
 17         if isinstance(self.urlconf_name, list) and len(self.urlconf_name):
 18             # Don‘t bother to output the whole list, it can be huge
 19             urlconf_repr = <%s list> % self.urlconf_name[0].__class__.__name__
 20         else:
 21             urlconf_repr = repr(self.urlconf_name)
 22         return str(<%s %s (%s:%s) %s>) % (
 23             self.__class__.__name__, urlconf_repr, self.app_name,
 24             self.namespace, self.regex.pattern)
 25 
 26     def _populate(self):
 27         lookups = MultiValueDict()
 28         namespaces = {}
 29         apps = {}
 30         language_code = get_language()
 31         for pattern in reversed(self.url_patterns):
 32             p_pattern = pattern.regex.pattern
 33             if p_pattern.startswith(^):
 34                 p_pattern = p_pattern[1:]
 35             if isinstance(pattern, RegexURLResolver):
 36                 if pattern.namespace:
 37                     namespaces[pattern.namespace] = (p_pattern, pattern)
 38                     if pattern.app_name:
 39                         apps.setdefault(pattern.app_name, []).append(pattern.namespace)
 40                 else:
 41                     parent = normalize(pattern.regex.pattern)
 42                     for name in pattern.reverse_dict:
 43                         for matches, pat, defaults in pattern.reverse_dict.getlist(name):
 44                             new_matches = []
 45                             for piece, p_args in parent:
 46                                 new_matches.extend([(piece + suffix, p_args + args) for (suffix, args) in matches])
 47                             lookups.appendlist(name, (new_matches, p_pattern + pat, dict(defaults, **pattern.default_kwargs)))
 48                     for namespace, (prefix, sub_pattern) in pattern.namespace_dict.items():
 49                         namespaces[namespace] = (p_pattern + prefix, sub_pattern)
 50                     for app_name, namespace_list in pattern.app_dict.items():
 51                         apps.setdefault(app_name, []).extend(namespace_list)
 52             else:
 53                 bits = normalize(p_pattern)
 54                 lookups.appendlist(pattern.callback, (bits, p_pattern, pattern.default_args))
 55                 if pattern.name is not None:
 56                     lookups.appendlist(pattern.name, (bits, p_pattern, pattern.default_args))
 57         self._reverse_dict[language_code] = lookups
 58         self._namespace_dict[language_code] = namespaces
 59         self._app_dict[language_code] = apps
 60 
 61     @property
 62     def reverse_dict(self):
 63         language_code = get_language()
 64         if language_code not in self._reverse_dict:
 65             self._populate()
 66         return self._reverse_dict[language_code]
 67 
 68     @property
 69     def namespace_dict(self):
 70         language_code = get_language()
 71         if language_code not in self._namespace_dict:
 72             self._populate()
 73         return self._namespace_dict[language_code]
 74 
 75     @property
 76     def app_dict(self):
 77         language_code = get_language()
 78         if language_code not in self._app_dict:
 79             self._populate()
 80         return self._app_dict[language_code]
 81 
 82     def resolve(self, path):
 83         tried = []
 84         match = self.regex.search(path)
 85         if match:
 86             new_path = path[match.end():]
 87             for pattern in self.url_patterns:
 88                 try:
 89                     sub_match = pattern.resolve(new_path)
 90                 except Resolver404 as e:
 91                     sub_tried = e.args[0].get(tried)
 92                     if sub_tried is not None:
 93                         tried.extend([[pattern] + t for t in sub_tried])
 94                     else:
 95                         tried.append([pattern])
 96                 else:
 97                     if sub_match:
 98                         sub_match_dict = dict(match.groupdict(), **self.default_kwargs)
 99                         sub_match_dict.update(sub_match.kwargs)
100                         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)
101                     tried.append([pattern])
102             raise Resolver404({tried: tried, path: new_path})
103         raise Resolver404({path : path})
104 
105     @property
106     def urlconf_module(self):
107         try:
108             return self._urlconf_module
109         except AttributeError:
110             self._urlconf_module = import_module(self.urlconf_name)
111             return self._urlconf_module
112 
113     @property
114     def url_patterns(self):
115         patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
116         try:
117             iter(patterns)
118         except TypeError:
119             raise ImproperlyConfigured("The included urlconf %s doesn‘t have any patterns in it" % self.urlconf_name)
120         return patterns
121 
122     def _resolve_special(self, view_type):
123         callback = getattr(self.urlconf_module, handler%s % view_type, None)
124         if not callback:
125             # No handler specified in file; use default
126             # Lazy import, since django.urls imports this file
127             from django.conf import urls
128             callback = getattr(urls, handler%s % view_type)
129         return get_callable(callback), {}
130 
131     def resolve403(self):
132         return self._resolve_special(403)
133 
134     def resolve404(self):
135         return self._resolve_special(404)
136 
137     def resolve500(self):
138         return self._resolve_special(500)
139 
140     def reverse(self, lookup_view, *args, **kwargs):
141         return self._reverse_with_prefix(lookup_view, ‘‘, *args, **kwargs)
142 
143     def _reverse_with_prefix(self, lookup_view, _prefix, *args, **kwargs):
144         if args and kwargs:
145             raise ValueError("Don‘t mix *args and **kwargs in call to reverse()!")
146         try:
147             lookup_view = get_callable(lookup_view, True)
148         except (ImportError, AttributeError) as e:
149             raise NoReverseMatch("Error importing ‘%s‘: %s." % (lookup_view, e))
150         possibilities = self.reverse_dict.getlist(lookup_view)
151 
152         prefix_norm, prefix_args = normalize(urlquote(_prefix))[0]
153         for possibility, pattern, defaults in possibilities:
154             for result, params in possibility:
155                 if args:
156                     if len(args) != len(params) + len(prefix_args):
157                         continue
158                     unicode_args = [force_text(val) for val in args]
159                     candidate = (prefix_norm + result) % dict(zip(prefix_args + params, unicode_args))
160                 else:
161                     if set(kwargs.keys()) | set(defaults.keys()) != set(params) | set(defaults.keys()) | set(prefix_args):
162                         continue
163                     matches = True
164                     for k, v in defaults.items():
165                         if kwargs.get(k, v) != v:
166                             matches = False
167                             break
168                     if not matches:
169                         continue
170                     unicode_kwargs = dict([(k, force_text(v)) for (k, v) in kwargs.items()])
171                     candidate = (prefix_norm.replace(%, %%) + result) % unicode_kwargs
172                 if re.search(^%s%s % (prefix_norm, pattern), candidate, re.UNICODE):
173                     return candidate
174         # lookup_view can be URL label, or dotted path, or callable, Any of
175         # these can be passed in at the top, but callables are not friendly in
176         # error messages.
177         m = getattr(lookup_view, __module__, None)
178         n = getattr(lookup_view, __name__, None)
179         if m is not None and n is not None:
180             lookup_view_s = "%s.%s" % (m, n)
181         else:
182             lookup_view_s = lookup_view
183         raise NoReverseMatch("Reverse for ‘%s‘ with arguments ‘%s‘ and keyword "
184                 "arguments ‘%s‘ not found." % (lookup_view_s, args, kwargs))

 

Django源码分析——urlresolvers.py

标签:

原文地址:http://www.cnblogs.com/IDomyself/p/4786812.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!