WebStack

docs/attributes.html

733:26865b172666
2007-11-12 paulb [project @ 2007-11-12 00:51:34 by paulb] Added a StringResource class for simple static resources. Introduced base classes for common authentication activities. Merged "app", "path" and "qs" fields into a single "app" field for login and redirection. Added support for OpenID authentication.
     1 <?xml version="1.0" encoding="iso-8859-1"?>     2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">     3 <html xmlns="http://www.w3.org/1999/xhtml"><head>     4   <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type" />     5   <title>Transaction Attributes</title>     6   <link href="styles.css" rel="stylesheet" type="text/css" /></head>     7 <body>     8 <h1>Transaction Attributes</h1>     9 <p>Sometimes, an application will process an incoming request using a number of different resource objects. For example, in the <a href="paths-filesystem.html">"Treating the Path Like a Filesystem"</a> document, an example is given which involves a number of&nbsp;<code>MapResource</code>    10 objects arranged in a hierarchy, and whilst such objects are used    11 merely to select other resources which are then used to provide some    12 kind of output, there may be other situations where such objects may    13 need to record some information about their activities, so that the    14 output-producing resource may customise the output accordingly.</p><p>In&nbsp;the example mentioned above, let    15 us consider the effect of replacing the special mapping from explicitly    16 specified year numbers with a new resource object that&nbsp;recognises    17 year numbers and&nbsp;dispatches requests to other resources:</p><pre>news_resource = YearResource({"document.html" : document_resource, "article.html" : article_resource})<br />documents_resource = MapResource({"news" : news_resource})<br />top_resource = MapResource({"documents" : documents_resource})</pre><p>What&nbsp;<code>YearResource</code> objects would do is to take the year number from the URL (see <a href="paths.html">"URLs and Paths"</a>)    18 and then to match a name in the dictionary it was initialised with, in    19 order to dispatch the transaction to a suitable resource. However, it    20 is likely that the year number is important to such resources: we would    21 expect to see a different Web page for&nbsp;<code>document.html</code> in&nbsp;<code>2005</code> than in&nbsp;<code>2004</code>, for example. Consequently, the&nbsp;<code>YearResource</code> needs a way to communicate such information to other resources.</p><p>Although we could provide special methods or change the parameters of the&nbsp;<code>respond</code> method in the&nbsp;<code>document_resource</code> and&nbsp;<code>article_resource</code>    22 objects in order to create a "channel" through which year information    23 could be passed, an alternative is to retain the existing interface and    24 behaviour of those objects and to store such information in the    25 transaction object itself. Since the transaction is&nbsp;essential in    26 the processing of any incoming request, we can be certain that it will    27 be available to store and to provide such information when necessary. </p><h2>Using Transaction Attributes</h2>    28 <p>We may obtain the attributes from the transaction by performing a method call as follows:</p><pre>        # In the respond method...<br />        attributes = trans.get_attributes()</pre><p>This    29 will provide a dictionary mapping names to&nbsp;attribute values. The    30 structure of the values is not strictly defined, and it is the    31 application's role to enforce its own rules on the data stored in the    32 attributes dictionary.</p><p>Setting and getting values is as straightforward as using a normal dictionary:</p>    33 <pre>        # Continuing from above...<br />        attributes["year"] = year<br />        # Later...<br />        if attributes.has_key("year"):<br />            year = attributes["year"]<br /></pre><p>As described in the <a href="../apidocs/public/WebStack.Generic.Transaction-class.html#get_attributes">API documentation</a>,    34 the attributes dictionary exists as long as the transaction object    35 itself. Should information need to be stored beyond the lifetime of a    36 transaction, the appropriate persistent information facilities should    37 be used instead - see <a href="sessions.html">"Sessions and Persistent Information"</a> for more details.</p><h2>Storing the Application Location in an Attribute</h2><p>One    38 use of attributes is to take the location of an application, defined in    39 terms of its path, and to store that information in an attribute. Such    40 information would then travel to different resources in an application    41 as part of the transaction, enabling those resources to generate things    42 like hyperlinks which contain "absolute" rather than "relative"    43 references to various parts of the application. Consider an application    44 deployed at the following URL:</p><pre>http://application.business.com/bizapp/</pre><p>Inside this application, we may have other URLs which expose certain functions:</p><pre>http://application.business.com/bizapp/services/finance/accounting<br />http://application.business.com/bizapp/services/customer/invoice</pre><p>It    45 may be interesting for these functions to know the location of the    46 top-level or root of the application in order to, for example, generate    47 hyperlinks to the top-level or to other established functions. Thus, we    48 may decide to remember the top-level path which would be the following:</p><pre>/bizapp/</pre><p>Now, normally the&nbsp;<code>get_path_without_info</code> method will provide this information, but what if we wanted to remember the following path instead...?</p><pre>/bizapp/services/</pre><p>In    49 fact, we can make use of the other path-related methods to obtain this    50 path, provided that we ask for this information at the correct point in    51 processing the request. Let us imagine that we have used the&nbsp;<a href="resource-map.html"><code>MapResource</code></a> class to build up the path hierarchy:</p><pre>resource = MapResource({<br />    "services" : MapResource({<br />        "finance" : finance_department,<br />        "customer" : customer_department<br />        })<br />    })</pre><p>We    52 would want to define a&nbsp;resource to process the request and    53 remember the path details just before choosing between the finance and    54 customer departments. This resource would do the following:</p><ol><li>Ask for the path without info, along with the processed virtual path info (as described in <a href="path-info.html">"Paths To and Within Applications"</a>).</li><li>Join the paths together.</li><li>Store the result on an attribute (called "root", perhaps).</li><li>Invoke another resource.</li></ol><p>The advantage of doing this dynamically is that should we decide to change the location of the application or the path to&nbsp;<code>services</code> within it, we will not need to track down hard-coded path values and change them in lots of different places.</p><p>Fortunately, WebStack provides a class to do this work for us -&nbsp;<code>PathSelector</code> - and we can use it in the following way:</p><pre>from WebStack.Resources.Selectors import PathSelector<br /><br />resource = MapResource({<br />    "services" : PathSelector(<br />        MapResource({<br />            "finance" : finance_department,<br />            "customer" : customer_department<br />            })<br />        )<br />    })</pre><p>Now, once the&nbsp;<code>services</code> part of the path has been detected, the&nbsp;<code>PathSelector</code> resource will discover the path details, store them on an attribute, and then invoke the <code>MapResource</code> which chooses between departments, which in turn invokes other resources, and so on. However, all of the resources "below" the <code>PathSelector</code>&nbsp;resource    55 will have an attribute called "root" which contains the selected "root    56 path" of the application (or at least the interesting part of the    57 application).</p><p>See the <a href="selectors.html">"Selectors"</a> document for more details of the  <code>PathSelector</code> class.</p></body></html>