summaryrefslogtreecommitdiff
path: root/docs/narr/urlmapping.rst
blob: 269061e40545ed9a1e4dde3185736ee78c6bd1dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
.. _url_mapping_chapter:

Mapping URLs to Code
====================

Many popular web frameworks today use :term:`URL dispatch` to
associate a particular URL with a bit of code (known somewhat
ambiguously as a "controller" or :term:`view` depending upon the
particular vocabulary religion to which you subscribe).  These systems
allow the developer to create "urlconfs" or "routes" to
controller/view Python code using pattern matching against URL
components.  Examples: `Django's URL dispatcher
<http://www.djangoproject.com/documentation/url_dispatch/>`_ and the
:term:`Routes` URL mapping system.

:mod:`repoze.bfg` supports :term:`URL dispatch` via a subsystem that
was inpsired by :term:`Routes`.  :term:`URL dispatch` is convenient
and straightforward.  When you limit your application to using URL
dispatch, you know every URL that your application might generate or
respond to, and all the URL matching elements are listed in a single
place.

Like :term:`Zope`, :mod:`repoze.bfg`, in contrast to URL dispatch, can
also map URLs to code slightly differently, by using using object
graph :term:`traversal`.  Graph-traversal based dispatching is useful
if you like your URLs to represent an arbitrary hierarchy of
potentially heterogeneous items, or if you need to attach
"instance-level" security (akin to "row-level" security in relational
parlance) declarations to :term:`model` instances.

Differences Between Traversal and URL Dispatch
----------------------------------------------

:term:`URL dispatch` can easily handle URLs such as
``http://example.com/members/Chris``, where it's assumed that each
item "below" ``members`` in the URL represents a member in the system.
You just match everything "below" ``members`` to a particular view.

For example, you might configure a :term:`route` to match against the
following URL patterns::

  archives/:year/:month/:day
  members/:membername

In this configuration, there are exactly two types of URLs that will
match views in your application: ones that start with ``/archives``
and have subsequent path elements that represent a year, month, and
day.  And ones that start with ``/members`` which are followed by a
path segment containing a member's name.  This is very simple.

:term:`URL dispatch` is not very good, however, at inferring the
difference between sets of URLs such as::

       http://example.com/members/Chris/document
       http://example.com/members/Chris/stuff/page

...wherein you'd like the ``document`` in the first URL to represent a
PDF document, and ``/stuff/page`` in the second to represent an
*OpenOffice* document in a "stuff" folder.  It takes more pattern
matching assertions to be able to make URLs like these work in
URL-dispatch based systems, and some assertions just aren't possible.
For example, URL-dispatch based systems don't deal very well with URLs
that represent arbitrary-depth hierarchies.

Graph :term:`traversal` works well if you need to divine meaning out
of these types of "ambiguous" URLs and URLs that represent
arbitrary-depth hierarchies.  Each URL segment represents a single
traversal through an edge of the graph.  So a URL like
``http://example.com/a/b/c`` can be thought of as a graph traversal on
the ``example.com`` site through the edges ``a``, ``b``, and ``c``.

If you're willing to treat your application models as a graph that can
be traversed, it also becomes easy to provide "row-level security" (in
common relational parlance): you just attach a security declaration to
each instance in the graph.  This is not as easy in frameworks that
use URL-based dispatch.

Graph traversal is materially more complex than URL-based dispatch,
however, if only because it requires the construction and maintenance
of a graph, and it requires the developer to think about mapping URLs
to code in terms of traversing the graph.  (How's *that* for
self-referential! ;-) ) 

In essence, the choice to use graph traversal vs. URL dispatch is
largely religious in some sense.  Graph traversal dispatch probably
just doesn't make any sense when you possess completely "square" data
stored in a relational database.  However, when you have a
hierarchical data store, it can provide advantages over using
URL-based dispatch.

:mod:`repoze.bfg` provides support for both approaches.  You can use
either as you see fit.