64 self.kwargs = {} |
64 self.kwargs = {} |
65 |
65 |
66 self.name = name |
66 self.name = name |
67 self.prefix = prefix |
67 self.prefix = prefix |
68 |
68 |
69 def makeDjangoUrl(self): |
69 def makeDjangoUrl(self, **extra_kwargs): |
70 """Returns a Django url() used by urlpatterns. |
70 """Returns a Django url() used by urlpatterns, or None if not a view. |
71 """ |
71 """ |
72 return defaults.url(self.regex, self.view, kwargs=self.kwargs, |
72 if not self.view: |
|
73 return None |
|
74 |
|
75 kwargs = copy.deepcopy(self.kwargs) |
|
76 kwargs.update(extra_kwargs) |
|
77 return defaults.url(self.regex, self.view, kwargs=kwargs, |
73 name=self.name, prefix=self.prefix) |
78 name=self.name, prefix=self.prefix) |
74 |
79 |
75 _STR_FMT = '''%(indent)sregex: %(regex)s |
80 _STR_FMT = '''%(indent)sregex: %(regex)s |
76 %(indent)sview: %(view)s |
81 %(indent)sview: %(view)s |
77 %(indent)skwargs: %(kwargs)s |
82 %(indent)skwargs: %(kwargs)s |
152 # and views to Pages possible (without requiring a recursive search) |
157 # and views to Pages possible (without requiring a recursive search) |
153 |
158 |
154 def getChildren(self): |
159 def getChildren(self): |
155 """Returns an iterator over any child Pages |
160 """Returns an iterator over any child Pages |
156 """ |
161 """ |
157 for page, _ in self.child_by_urls.itervalues(): |
162 for page in self.child_by_views.itervalues(): |
158 yield page |
163 yield page |
159 |
164 |
160 children = property(getChildren) |
165 children = property(getChildren) |
161 |
166 |
162 def getChild(self, url=None, regex=None, view=None, |
167 def getChild(self, url=None, regex=None, view=None, |
222 """ |
227 """ |
223 # TODO(tlarsen): see also TODO in __init__() about global Page dictionary |
228 # TODO(tlarsen): see also TODO in __init__() about global Page dictionary |
224 |
229 |
225 url = page.url |
230 url = page.url |
226 |
231 |
227 if not isinstance(url.regex, basestring): |
232 if url.regex: |
228 raise ValueError('"regex" must be a string, not a compiled regex') |
233 if not isinstance(url.regex, basestring): |
229 |
234 raise ValueError('"regex" must be a string, not a compiled regex') |
230 # TODO(tlarsen): see if Django has some way exposed in its API to get |
235 |
231 # the view name from the request path matched against urlpatterns; |
236 # TODO(tlarsen): see if Django has some way exposed in its API to get |
232 # if so, there would be no need for child_by_urls, because the |
237 # the view name from the request path matched against urlpatterns; |
233 # request path could be converted for us by Django into a view/name, |
238 # if so, there would be no need for child_by_urls, because the |
234 # and we could just use child_by_views with that string instead |
239 # request path could be converted for us by Django into a view/name, |
235 self.child_by_urls[url.regex] = (page, re.compile(url.regex)) |
240 # and we could just use child_by_views with that string instead |
|
241 self.child_by_urls[url.regex] = (page, re.compile(url.regex)) |
|
242 # else: NonUrl does not get indexed by regex, because it has none |
236 |
243 |
237 # TODO(tlarsen): make this work correctly if url has a prefix |
244 # TODO(tlarsen): make this work correctly if url has a prefix |
238 # (not sure how to make this work with include() views...) |
245 # (not sure how to make this work with include() views...) |
239 if url.name: |
246 if url.name: |
240 if not isinstance(url.name, basestring): |
247 if not isinstance(url.name, basestring): |
287 # TODO(tlarsen): make this work correctly with prefixes |
294 # TODO(tlarsen): make this work correctly with prefixes |
288 regex = self.child_by_views[view].url.regex |
295 regex = self.child_by_views[view].url.regex |
289 elif name in self.child_views: |
296 elif name in self.child_views: |
290 regex = self.child_by_views[name].url.regex |
297 regex = self.child_by_views[name].url.regex |
291 |
298 |
292 # regex must refer to an existing Page at this point |
299 if regex: |
293 del self.child_urls[regex] |
300 # regex must refer to an existing Page at this point |
|
301 del self.child_urls[regex] |
294 |
302 |
295 if not isinstance(view, basestring): |
303 if not isinstance(view, basestring): |
296 # use name if view is callable() or None, etc. |
304 # use name if view is callable() or None, etc. |
297 view = name |
305 view = name |
298 |
306 |
358 self.short_name, value=link_url, sub_menu=sub_menu) |
369 self.short_name, value=link_url, sub_menu=sub_menu) |
359 |
370 |
360 def makeDjangoUrl(self): |
371 def makeDjangoUrl(self): |
361 """Returns the Django url() for the underlying self.url. |
372 """Returns the Django url() for the underlying self.url. |
362 """ |
373 """ |
363 return self.url.makeDjangoUrl() |
374 return self.url.makeDjangoUrl(page=self) |
364 |
375 |
365 def makeDjangoUrls(self): |
376 def makeDjangoUrls(self): |
366 """Returns an ordered mapping of unique Django url() objects. |
377 """Returns an ordered mapping of unique Django url() objects. |
367 |
378 |
368 Raises: |
379 Raises: |
377 """Returns an ordered mapping of unique Django url() objects. |
388 """Returns an ordered mapping of unique Django url() objects. |
378 |
389 |
379 Used to implement makeDjangoUrls(). See that method for details. |
390 Used to implement makeDjangoUrls(). See that method for details. |
380 """ |
391 """ |
381 urlpatterns = NoOverwriteSortedDict() |
392 urlpatterns = NoOverwriteSortedDict() |
382 |
393 |
383 if self.url.view: |
394 django_url = self.makeDjangoUrl() |
384 urlpatterns[self.url.regex] = self.makeDjangoUrl() |
395 |
|
396 if django_url: |
|
397 urlpatterns[self.url.regex] = django_url |
385 |
398 |
386 for child in self.children: |
399 for child in self.children: |
387 urlpatterns.update(child._makeDjangoUrlsDict()) |
400 urlpatterns.update(child._makeDjangoUrlsDict()) |
388 |
401 |
389 return urlpatterns |
402 return urlpatterns |
416 |
429 |
417 def __str__(self): |
430 def __str__(self): |
418 """Returns a string representation useful for logging. |
431 """Returns a string representation useful for logging. |
419 """ |
432 """ |
420 return self.asIndentedStr() |
433 return self.asIndentedStr() |
|
434 |
|
435 |
|
436 class NonUrl(Url): |
|
437 """Placeholder for when a site-map entry is not a linkable URL. |
|
438 """ |
|
439 |
|
440 def __init__(self, name): |
|
441 """Creates a non-linkable Url placeholder. |
|
442 |
|
443 Args: |
|
444 name: name of the non-view placeholder |
|
445 """ |
|
446 Url.__init__(self, None, None, name=name) |
|
447 |
|
448 def makeDjangoUrl(self, **extra_kwargs): |
|
449 """Always returns None, since NonUrl is never a Django view. |
|
450 """ |
|
451 return None |
|
452 |
|
453 |
|
454 class NonPage(Page): |
|
455 """Placeholder for when a site-map entry is not a displayable page. |
|
456 """ |
|
457 |
|
458 def __init__(self, non_url_name, long_name, **page_kwargs): |
|
459 """ |
|
460 """ |
|
461 non_url = NonUrl(non_url_name) |
|
462 Page.__init__(self, non_url, long_name, **page_kwargs) |