Stuart Hungerford wrote: > Hi all, > > More newbie questions. I'm trying to get a feel for the idioms > that people use in creating real-world Quixote applications, > especially when dealing with the design choices involved in > mapping URL's to callables or namespaces. > > Suppose I plan to support this URL schema at example.org: > > http://example.org/ > http://example.org/foo > http://example.org/bar/baz > http://example.org/bar/fiz > > Assuming that Apache re-writing is re-writing these URLs to > the corresponding .../cgi-bin/ URLS for the local setup. > > Suppose the Quixote driver script loads the module "example.web". > Then the _q_exports instance for "example.web" could contain > simple callables (functions or templates) to implement the > first and second URL's > > _q_exports = ["_q_index", "foo"] > > For the third and fourth URL's however I could add a submodule > "example.web.bar" with callables "baz" and "fiz", OR I could > create a class with "baz", "fiz" member functions > (or _q_lookup())? Right. But you must be explicit in your exports: "bar" must also be included; importing it isn't enough. The bar module doesn't have to live in the example.web package, but of course it's a good organizational practice. _q_lookup() is the exception to the _q_exports rule. But it wouldn't make sense to just look up a static module that you could simply import (and then export). > > I *think* going the class route means you must use a _q_lookup() > function within "example.web" module to catch the "bar" component > of the URL and return a class instance that can then be traversed? Only if it's turly a dynamic lookup. If 'baz' and 'fiz' refer to methods rather than to named instances (lookups), then just define 'baz' and 'fiz' as methods in your class, then add the attribute _q_exports = ['baz', 'fiz'] to your class definition. If they refer to instances, then _q_lookup is your friend. And yes, it's a common practice to return a class instance that can be traversed. Note that you don't *have* to do this; you could also return any other traversable namespace. Personally I like to use modules instead of classes for my user interface code, so I often use a pattern like this in my lookups: # ---------- widgets/web/main.ptl import my_database import widget_ui # a module that knows how to render a Widget def _q_lookup(req, name): w = my_database.get_widget(name) if w: req.widget = w # add the widget to the *request* namespace return widget_ui # return a static module that expects this. # ---------- widgets/web/widget_ui.ptl ... def _q_index [html] (req): ... "the widget you have asked for is " req.widget.get_description() Your mileage may indeed vary! > Which of these approaches (or other approaches) are more quixotic? > Do Quixote developers end up in practice relying on _q_lookup() > heavily for traversing deep URLs, or do they favour a more 1-1 > mapping to callables?I think there should be a rough correspondence between the breadth/depth of your data structure and the breadth/depth of your URL space. If your database is very hierarchical, then you'll probably end up with a deep nesting. No matter the shape of your data, a good correspondence here will make your app more understandable (to yourself, your users and future maintainers of your code). -- Graham