app/soc/logic/site/page.py
changeset 372 8595c1129c74
parent 281 7caa8951cbc9
child 390 d12c95ade374
equal deleted inserted replaced
371:6dad90b78770 372:8595c1129c74
    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 
   316     if self.link_url:
   324     if self.link_url:
   317       return self.link_url
   325       return self.link_url
   318 
   326 
   319     link = self.url.regex
   327     link = self.url.regex
   320     
   328     
       
   329     if not link:
       
   330       return None
       
   331 
   321     if link.startswith('^'):
   332     if link.startswith('^'):
   322       link = link[1:]
   333       link = link[1:]
   323     
   334     
   324     if link.endswith('$'):
   335     if link.endswith('$'):
   325       link = link[:-1]
   336       link = link[:-1]
   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)