From e62e479e338e428f6cfd3b07790545982b7cb94f Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Tue, 27 Jan 2009 21:57:11 +0000 Subject: Features -------- - The ``repoze.bfg.url.model_url`` API now works against contexts derived from Routes URL dispatch (``Routes.util.url_for`` is called under the hood). - "Virtual root" support for traversal-based applications has been added. Virtual root support is useful when you'd like to host some model in a :mod:`repoze.bfg` model graph as an application under a URL pathname that does not include the model path itself. For more information, see the (new) "Virtual Hosting" chapter in the documentation. - A ``repoze.bfg.traversal.virtual_root`` API has been added. When called, it returns the virtual root object (or the physical root object if no virtual root has been specified). Implementation Changes ---------------------- - ``repoze.bfg.traversal.RoutesModelTraverser`` has been moved to ``repoze.bfg.urldispatch``. - ``model_url`` URL generation is now performed via an adapter lookup based on the context and the request. - ZCML which registers two adapters for the ``IContextURL`` interface has been added to the configure.zcml in ``repoze.bfg.includes``. --- repoze/bfg/url.py | 55 ++++++++++++++++++------------------------------------- 1 file changed, 18 insertions(+), 37 deletions(-) (limited to 'repoze/bfg/url.py') diff --git a/repoze/bfg/url.py b/repoze/bfg/url.py index a51333353..9ea82ed7a 100644 --- a/repoze/bfg/url.py +++ b/repoze/bfg/url.py @@ -3,43 +3,28 @@ import re import urllib -from zope.component import queryUtility -from zope.interface import implements - -from repoze.bfg.location import lineage -from repoze.bfg.interfaces import IURLGenerator - -class DefaultURLGenerator(object): - implements(IURLGenerator) - def model_url(self, model, request): - rpath = [] - for location in lineage(model): - name = location.__name__ - if name: - rpath.append(_urlsegment(name)) - if rpath: - prefix = '/' + '/'.join(reversed(rpath)) + '/' - else: - prefix = '/' - return request.application_url + prefix - -default_url_generator = DefaultURLGenerator() +from zope.component import getMultiAdapter +from repoze.bfg.interfaces import IContextURL +from repoze.bfg.interfaces import VH_ROOT_KEY def model_url(model, request, *elements, **kw): """ - Generate a string representing the absolute URL of the model - object based on the ``wsgi.url_scheme``, ``HTTP_HOST`` or + Generate a string representing the absolute URL of the model (or + context) object based on the ``wsgi.url_scheme``, ``HTTP_HOST`` or ``SERVER_NAME`` in the request, plus any ``SCRIPT_NAME``. If a + 'virtual root path' is present in the request environment (the + value of the environ key ``%s``), and the ``model`` was obtained + via traversal, the URL path will not include the virtual root + prefix (it will be stripped out of the generated URL). If a ``query`` keyword argument is provided, a query string based on its value will be composed and appended to the generated URL string (see details below). The overall result of this function - is always a string (never unicode). The ``model`` passed in must - be :term:`location`-aware. + is always a UTF-8 encoded string (never unicode). - .. note:: If any model in the lineage has a unicode name, it will - be converted to UTF-8 before being attached to the URL. - When composing the path based on the model lineage, - empty names in the model graph are ignored. + .. note:: If the ``model`` used is the result of a traversal, it + must be :term:`location`-aware. The 'model' can also be the + context of a URL dispatch; contexts found this way do not need + to be location-aware. Any positional arguments passed in as ``elements`` must be strings or unicode objects. These will be joined by slashes and appended @@ -63,19 +48,16 @@ def model_url(model, request, *elements, **kw): the resulting string is appended to the generated URL. .. note:: Python data structures that are passed as ``query`` - whichare sequences or dictionaries are turned into a + which are sequences or dictionaries are turned into a string under the same rules as when run through urllib.urlencode with the ``doseq`` argument equal to ``True``. This means that sequences can be passed as values, and a k=v pair will be placed into the query string for each value. - """ - - urlgenerator = queryUtility(IURLGenerator) - if urlgenerator is None: - urlgenerator = default_url_generator + """ % VH_ROOT_KEY - model_url = urlgenerator.model_url(model, request) + context_url = getMultiAdapter((model, request), IContextURL) + model_url = context_url() if 'query' in kw: qs = '?' + urlencode(kw['query'], doseq=True) @@ -87,7 +69,6 @@ def model_url(model, request, *elements, **kw): else: suffix = '' - app_url = request.application_url # never ends in a slash return model_url + suffix + qs def urlencode(query, doseq=False): -- cgit v1.2.3