Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

Changeset 797

Show
Ignore:
Timestamp:
11/07/05 19:04:07
Author:
fumanchu
Message:

Docs: new section on mapping URI's to handlers (for app developers). More to come soon.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/docs/book/xml/appdeveloperreference.xml

    r650 r797  
    1313    application.</abstract> 
    1414    <xi:include href="globaloverviewcherrypy.xml" /> 
     15    <xi:include href="usingfilters.xml" /> 
    1516    <xi:include href="configsystemoverview.xml" /> 
    1617    <xi:include href="sessions.xml" /> 
  • trunk/docs/book/xml/globaloverviewcherrypy.xml

    r627 r797  
    11<?xml version="1.0" encoding="UTF-8"?> 
    2 <section xmlns:db="http://docbook.org/docbook-ng" 
    3          xmlns:xi="http://www.w3.org/2001/XInclude" 
    4          xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    5          xml:id="globaloverviewcherrypy"> 
    6   <title>Filters</title> 
    7   <para>Filters are one of the most important features of CherryPy. The 
    8   CherryPy core can call user-defined functions at specific points during 
    9   request processing; a filter is a class which defines those functions. 
    10   Filters are designed to be called at a low level—the HTTP request/response 
    11   level—and therefore should only be used in that context.</para> 
    12   <para>CherryPy comes with a set of built-in filters, but they're turned off 
    13   by default. To enable them, you must use the configuration system as 
    14   follows:</para> 
    15   <itemizedlist> 
    16     <listitem>First you must decide where to enable the filter. CherryPy 
    17     maintains a tree of published objects; you must decide which branch should 
    18     use the filter. The filter will then apply to that branch and all its 
    19     children in the tree. Remember that the tree is accessed as a path and 
    20     then mapped internally by the core to match the correct exposed 
    21     object.</listitem> 
    22     <listitem>Second in the config file you must turn the filter on like this 
    23     : <code>filterName.on = True</code></listitem> 
    24   </itemizedlist> 
    25   <example> 
    26     <title>Turning on a default filter</title> 
    27     <programlisting linenumbering="numbered"> 
    28         [/entries/view] 
    29         tidyFilter.on = True 
    30         tidyFilter.tmpDir = "/tmp" 
    31         tidyFilter.strictXml = True 
    32       </programlisting> 
    33   </example> 
    34   <para>On the first line we define that the tidy filter will be used by the 
    35   core whenever the path <code>/entries/view</code> (or one of its sub-paths) 
    36   is called. On the two last lines we also define some parameters used by the 
    37   filter.</para> 
    38   <para>CherryPy lets you write your own filters as we will see in the 
    39   developer reference chapter. However, the way to use them is different from 
    40   the default filters. You do not declare custom filters within the 
    41   configuration file; instead, use the <code>_cpFilterList</code> attribute in 
    42   your source code:</para> 
    43   <example> 
    44     <title>Using a non default filter</title> 
    45     <programlisting linenumbering="numbered"> 
    46         import cherrypy 
    47         from myfiltermodule import MyFilterClass 
    48          
    49         class Entry: 
    50           _cpFilterList = [ MyFilterClass() ] 
    51           def view(self, id):  
    52             # do suff... 
    53           view.exposed = True 
    54          
    55         class Root: pass 
    56          
    57         cherrypy.root = Root() 
    58         cherrypy.root.entries = Entry() 
    59         cherrypy.server.start() 
    60       </programlisting> 
    61   </example> 
    62   <para>As all objects below <code>cherrypy.root.entries</code> will inherit 
    63   the filter, there is no need to re-specify it in each 
    64   <code>_cpFilterList</code> underneath.</para> 
    65   <para>Keep in mind that the user-defined filters are called in the order you 
    66   add them to the list.</para> 
     2<section xmlns:db="http://docbook.org/docbook-ng" xmlns:xi="http://www.w3.org/2001/XInclude" 
     3         xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xml:id="globaloverviewcherrypy"> 
     4    <title>Global Overview</title> 
     5    <section> 
     6        <title>Mapping URI's to handlers</title> 
     7        <para>CherryPy has lots of fancy features to help you manage HTTP messages. But the most 
     8        fundamental thing it does is allow you to map URI's to handler functions. It does this in a 
     9        very straightforward way: the path portion of a URI is heirarchical, so CherryPy uses a 
     10        parallel heirarchy of objects, starting with <code>cherrypy.root</code>. If your application 
     11        receives a request for "/admin/user?name=idunno", then CherryPy will try to find the handler: 
     12        <code>cherrypy.root.admin.user</code>. If it exists, is callable, and has an "exposed = True" 
     13        attribute, then CherryPy will hand off control to that function. Any URI parameters (like 
     14        "name=idunno", above) are passed to the handler as keyword arguments.</para> 
     15        <section> 
     16            <title>Index methods</title> 
     17            <para>There are some special cases, however. To what handler should we map a path like 
     18            "/admin/search/"? Note the trailing slash after "search"—it indicates that our path has 
     19            three components: "admin", "search", and "". Static webservers interpret this to mean 
     20            that the <code>search</code> object is a directory, and, since the third component is 
     21            blank, they use an <code>index.html</code> file if it exists. CherryPy is a dynamic 
     22            webserver, so it allows you to specify an <code>index</code> method to handle this. In 
     23            our example, CherryPy will look for a handler at 
     24            <code>cherrypy.root.admin.search.index</code>. Let's pause and show our example 
     25            application so far:</para> 
     26            <example> 
     27                <title>Sample application (handler mapping example)</title> 
     28                <programlisting>import cherrypy 
     29 
     30class Root: 
     31    def index(self): 
     32        return "Hello, world!" 
     33    index.exposed = True 
     34 
     35class Admin: 
     36    def user(self, name=""): 
     37        return "You asked for user '%s'" % name 
     38    user.exposed = True 
     39 
     40class Search: 
     41    def index(self): 
     42        return search_page() 
     43    index.exposed = True 
     44 
     45cherrypy.root = Root() 
     46cherrypy.root.admin = Admin() 
     47cherrypy.root.admin.search = Search()</programlisting> 
     48            </example> 
     49            <para>So far, we have three exposed handlers:</para> 
     50            <itemizedlist> 
     51                <listitem> 
     52                    <para><code>root.index</code>. This will be called for the URI's "/" and 
     53                    "/index".</para> 
     54                </listitem> 
     55                <listitem> 
     56                    <para><code>root.admin.user</code>. This will be called for the URI 
     57                    "/admin/user".</para> 
     58                </listitem> 
     59                <listitem> 
     60                    <para><code>root.admin.search.index</code>. This will be called for the URI's 
     61                    "/admin/search/" and "/admin/search".</para> 
     62                </listitem> 
     63            </itemizedlist> 
     64            <para>Yes, you read that third line correctly: <code>root.admin.search.index</code> will 
     65            be called whether or not the URI has a trailing slash. Actually, that isn't quite true; 
     66            CherryPy will answer a request for "/admin/search" (without the slash) with an HTTP 
     67            Redirect response. Most browsers will then request "/admin/search/" as the redirection 
     68            suggests, and <emphasis>then</emphasis> our <code>root.admin.search.index</code> handler 
     69            will be called. But the final outcome is the same.</para> 
     70        </section> 
     71        <section> 
     72            <title>Positional Parameters</title> 
     73            <para>Now, let's consider another special case. What if, instead of passing a user name 
     74            as a parameter, we wish to use a user id as part of the path? What to do with a URI like 
     75            "/admin/user/8173/schedule"? This is intended to reference the schedule belonging to 
     76            "user #8173", but we certainly don't want to have a separate function for each user 
     77            id!</para> 
     78            <para>CherryPy allows you to map a single handler to multiple URI's with the simple 
     79            approach of <emphasis>not writing handlers you don't need</emphasis>. If a node in the 
     80            <code>cherrypy.root</code> tree doesn't have any children, that node will be called for 
     81            all of its child paths, and CherryPy will pass the leftover path info as positional 
     82            arguments. In our example, CherryPy will call <code>cherrypy.root.admin.user("8173", 
     83            "schedule")</code>.</para> 
     84        </section> 
     85    </section> 
    6786</section> 

Hosted by WebFaction

Log in as guest/cpguest to create tickets