1. Trang chủ
  2. » Công Nghệ Thông Tin

zope bible phần 9 ppsx

65 258 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 65
Dung lượng 529,08 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Indexes are the lookup tables that the ZCatalog consults inorder to determine which objects match a particular query, and metadata is theinformation about an object that a ZCatalog store

Trang 1

To distribute your Product, select the Distribution tab from within the product Forexample, click the Distribution tab within the ZFAQ product.

The form on the Distribution tab gives you fine control over the distribution youcreate The Version field specifies the version that will be visible in the products listfor whoever installs the product Every time you make a distribution, the numberwill be incremented, but you can change it to whatever number you want We sug-gest leaving it at 1.0 unless you have some reason to do otherwise

Next on the form, there are two radio-buttons that let you select the kind ofDistribution you want to create If you want others to be able to customize and/orredistribute your Product, select the “Allow Redistribution” option If you want todisallow redistribution, select the “Disallow redistribution and allow the user toconfigure only the selected objects:” option, and you can choose which objectsyour users can customize in your Product The list defaults to having no objectsselected, which won’t allow any changes to the distributed product If you wantthem to be able to change the FAQManager ZClass, select that ZClass If you wantthe whole product to be customizable but still disallow redistribution, select all ofthe objects in the list Notice that the QandA Zclass, which is contained within theFAQManager Zclass, is not listed within this object list This means that there is noway to allow or disallow customization of the QandA ZClass independently from theFAQManager ZClass Whether the QandA Zclass is customizable is dependent onthe whether the FAQManager ZClass is customizable To get around this limitation,the QandA object would have to have been created in a separate product

After you made your decisions regarding the redistribution and customization of theZFAQ product distribution, click the Create a distribution archive button Zope willnow create a file called ZFAQ-1.0.tar.gz, and attempt to download it to your com-puter Save the file on your desktop or in a “Downloads” directory on your computer.The ZFAQ-1.0.tar.gz file can be installed in a Zope installation just like any otherdownloaded product If you think that your product would be useful to other Zopeusers, we suggest that you add your product to your zope.org member folder tomake it generally available

Summary

In this chapter, you learned about creating through-the-Web products usingZClasses, defining property sheets and views, and building a simple Web applica-tion using them You also learned to add permissions to ZClasses, make yourZClasses CatalogAware, subclass Python classes in your ZClass products, anddistribute your through-the-Web products

Trang 2

Searching Content

Most of this book describes using Zope to accomplish

fairly ordinary Web site building and maintenancetasks Even Part II of the book, which shows you how to buildcustom object types using Zope’s object oriented framework,isn’t that different from building a similar application usingJavaBeans, for example

In this chapter, we are going to introduce one of Zope’s tures that sets Zope apart from other Web development envi-ronments — its integrated framework for indexing andsearching objects and their attributes

fea-Adding and Populating ZCatalogs

Zope has built-in searching and indexing capabilities thatenable you to easily find objects in your site that conform tovarious criteria (such as containing some text) via ad-hocqueries

What is a ZCatalog?

ZCatalogs are Zope’s general-purpose search engines andindexers A ZCatalog examines objects, indexes whateverproperties you’ve marked as significant, and enables you toquery the ZCatalog for objects whose properties match yourcriteria Additionally, ZCatalogs don’t return the actualobjects in their results, but instead return a speciallightweight object with whatever metadata you’ve told theZCatalog to retain for the object and a pointer to the actualobject if you need it

17C H A P T E R

In This Chapter

Adding andpopulating ZCatalogsConfiguring andquerying theZCatalogAccessing ZCatalogsfrom Python

More about ZCatalog

Trang 3

Adding a ZCatalog to your site

In your root folder, click on the drop-down to select ZCatalog from the list ofaddable products Fill the Add ZCatalog form that comes up with an id of Catalog,leave the title field blank, and leave the vocabulary drop-down set on the default ofCreate one for me(we’ll go into more detail about Vocabularies in the “AboutVocabularies” sidebar in the “More about ZCatalog” section) Click the Add button.You should now have a ZCatalog instance named Catalogin your root folder Theicon for a ZCatalog is a folder with a magnifying glass, and the ZCatalog user inter-face does resemble that of a folder somewhat But there are a few differences, asshown in Figure 17-1

Figure 17-1: The ZCatalog Contents tab

ZCatalogs have several tabs that folders do not have, including the following: Catalog

IndexesMetadataAdvanced The Find tab that folders have is replaced with a Find Objects tab in a ZCatalog

Trang 4

Populating a ZCatalog

ZCatalogs can be populated in two ways: manually and automatically Populating aZCatalog manually is fairly simple; just go to the Find Objects tab in a ZCatalog(shown in Figure 17-2), and select the criteria for the objects that you want to cata-log and index

Figure 17-2: The ZCatalog Find Objects tab

For the time being, leave the default settings in the form, and click the Find andCatalog button at the bottom of the form The operation may take a few moments,

so be patient while Zope works

After Zope is done finding and cataloging the objects that meet the criteria youspecified (in this case, all objects stored in the ZODB), the browser is redirected tothe Catalog tab of the ZCatalog, and it shows you how long it took to complete theoperation, as shown in Figure 17-3

As you can see, the find objects operation found all objects in the ZODB, all ofwhich are now recorded in the ZCatalog

Trang 5

Figure 17-3: The Catalog tab, after finding objects

Configuring and Querying the ZCatalog

ZCatalogs store two types of information about the objects that they catalog:indexes and metadata Indexes are the lookup tables that the ZCatalog consults inorder to determine which objects match a particular query, and metadata is theinformation about an object that a ZCatalog stores in order to make its result setsmore meaningful

ZCatalog indexes

The ZCatalog uses indexes to determine which objects that it knows about match aparticular query In order for you to query a ZCatalog about a particular objectattribute, that attribute must be indexed by the ZCatalog in an Index As you cansee in Figure 17-4, the ZCatalog’s index tab has several indexes by default

Trang 6

Figure 17-4: The ZCatalog Indexes tab

The following are the four built-in types of indexes:

✦ Text indexes These indexes break up text contained in an attribute into

indi-vidual words The more times a particular word appears in an attributeindexed by a text index, the higher its score Results are sorted by score, high-est to lowest from the most relevant to the lest relevant Text indexes areoften referred to as full-text indexes PrincipiaSearchSourceand titlearetext indexes included in a ZCatalog by default

✦ Field indexes These indexes treat the object’s attribute as a single unit, and

they are used to keep track of object attributes that conform to a particularvalue Field indexes included in a ZCatalog by default are bobobase_

modification_time, id, and meta_type.

✦ Keyword indexes These indexes take a sequence of objects and break them

up into keywords, which are then indexed individually A Keyword indexreturns any objects that have one or more indexed keywords that match anykeywords from the query They are particularly useful for building categories

✦ Path indexes These indexes break up the physical path to an indexed object

into all its subpaths A Path index returns all objects that match a partial pathspecified in a search query By default, a ZCatalog includes a path indexnamed path

Trang 7

You may be wondering what the heck bobobase_modification_time and

PrincipiaSearchSourceare These attribute names date back to the dim tory of Zope, before the source had been released, and even before it was namedZope In those days, the ZODB had been called Bobo, apparently chosen as “aname so stupid, it would have to be replaced,” and the ZPublisher was calledPrincipia bobobase_modification_timeis an attribute that stores the last timethat an object was modified, and PrincipiaSearchSource is an attribute ormethod that an object can use to expose whatever text is most appropriate to beindexed with a Text index A book object for example might have a

prehis-PrincipiaSearchSourcemethod that returns a concatenation of the book’s title,author name, description, and keyword attributes This would ensure that a singletext index would index all of the book objects’ textual attributes, making them eas-ily searchable There is further detail in the “More about text indexes” sectiontowards the end of the chapter

Adding a new index is easy, just choose the type of index you want to add from thedrop-down box on the Indexes tab, fill in the Add Index form that comes up, andclick the Add button

When a ZCatalog indexes an object, it uses the defined indexes to determine whatattributes get examined The index id is also the name of the attribute that it willexamine for each cataloged object It’s easy to see, then, that the titleindex willoperate on the title attribute of cataloged objects As you know, not all objectswithin Zope have a title attribute In those cases, the index ignores the object.Removing an index is similarly easy Just select the checkbox next to the indexesyou wish to delete, and click the Remove Index button

Clearing an index does just what it sounds like It wipes an index clean of the valuesthat it has stored, and of the associations from those values to the objects theycame from You can clear an index by selecting the checkbox to the left of theindex, and clicking the Clear Index button

Reindexing examines the objects the Catalog knows about, and updates the valuesstored by the indexes that you’ve selected You can use this to repopulate an indexafter it has been cleared, but this will not find any new objects that are not in theZCatalog already You can reindex the ZCatalog’s indexes by selecting the checkboxnext to an index, and clicking the Reindex button

ZCatalog indexes don’t have to target attributes, they can also be directed to indexobject methods This means that you can index on the result of some calculation.Suppose that your object has a method for returning a list of related_items, andthat the method calculated which objects were related according to some criteriayou selected By indexing this method, you can search the ZCatalog for all objectsthat consider themselves related to the currently displayed object (not just theobjects that the current object’s related_itemsmethod returns)

Note

Trang 8

ZCatalog Metadata

Metadata, or “data about data,” are the attributes that the ZCatalog stores for eachobject, not for the purposes of querying, but for the purpose of returning results InFigure 17-5, you can see the metadata that a ZCatalog is set to store by default:

Adding a new metadata field is simple Just type the name of the attribute that youwant to track into the Add Metadata field at the bottom of the Metadata tab, andclick the Add button Deleting a metadata field is as simple as selecting the check-box next to the field name and clicking Delete

It’s worth noting that as with Indexes, metadata fields can reference methods, notjust attributes So, for example, if your object has a method that returns the result

of a calculation (say, popularity), you can store that as metadata as well, and returnthis in your query results list

Trang 9

Figure 17-5: The ZCatalog’s Metadata tab

Building search interfaces

Zope includes the capability to automatically generate search interfaces forZCatalogs based on the indexes and metadata stored in the ZCatalog

In the root folder, choose Z Search Interface from the drop-down box An AddSearch Interface form comes up (see Figure 17-6), with several fields The first is alist of the searchable objects (ZCatalogs) that you can set the search interface totarget Select Catalog Next is the report id, which is the id of the DTML Method that

will display the results list Type search_results You may leave the report title and search input title blank, but type search_form into the search input id field All that

remains is to choose the form of the report that will be generated

You can choose a tabular format or a records format for the report They both tain and present the same information; the only difference is in the HTML code that

con-is generated In the tabular format, each result in the result lcon-ist gets a row in a table,

Trang 10

with each metadata field in its own cell and the metadata columns labeled at thetop of the table In the records format, each result in the result list is in its ownparagraph, with the metadata fields separated by commas I generally use the tabu-lar format.

Figure 17-6: The Add Search Interface form

At the bottom of the form, you also have the option of selecting whether DTMLMethods or Page Templates will be generated Page Templates are a relatively newaddition to Zope, so while we encourage you to explore their use (and read Chapter18), the rest of this chapter will only discuss using DTML Methods So select theDTML Methods radio button

After you’ve filled in the form, click the Add button, and after a brief pause, you arereturned to the Contents view of the root folder Two new DTML methods are there:

search_formand search_results

Trang 11

Listing 17-1: The search_form method

no values need to be passed in explicitly This is why the attribute, the index, andthe form field all share the same id — to make this transparency possible

Trang 12

Listing 17-2: The search_results method (tabular)

(Previous <dtml-var previous-sequence-size> results)

(Next <dtml-var next-sequence-size> results)

</a>

Continued

Trang 13

(Previous <dtml-var previous-sequence-size> results)

Trang 14

<a href=”<dtml-var URL><dtml-var sequence-query

>query_start=<dtml-varnext-sequence-start-number>”>

(Next <dtml-var next-sequence-size> results)

Trang 15

You can see that the search form has a field for each index When you click on theSubmit Query button without entering any search parameters, the Catalog returnsall objects that it has cataloged Depending on whether you selected a tabular for-mat or a records format when you generated the search interface, you see a resultspage like the one shown in either Figure 17-8 or Figure 17-9.

Figure 17-8: The search_resultsmethod (tabular format)

You can link from the search results list to the actual objects by changing theoccurrence of <dtml-var id>in either the Tabular or Records results format to thefollowing code:

<a href=”&dtml-getURL;”><dtml-var id></a>

This takes advantage of the getURL attribute that the result object (colloquiallyknown as a brain) has, which refers to the actual object that was cataloged

Tip

Trang 16

Figure 17-9: The search_resultsmethod (records format)

Accessing ZCatalogs from Python

You can access ZCatalogs from Python script objects and from within Python-basedproduct code, not just using DTML search interfaces This lets you use your siteslogic and behavior to query the ZCatalog programmatically

Accessing ZCatalogs from Python script objects

Consider the following Python script object, named about_objects:

x = context.Catalog({‘PrincipiaSearchSource’: ‘about’})

z = []

for y in x:

z.append(y.getObject())return z

You can call the script from a DTML method, like this:

Trang 17

Calling from a DTML method, as in the preceding code, produces a list of links to allcataloged documents containing the word about The catalog is being passed a dic-tionary, where the key is the index id, and the value is the indexed value that we’relooking for.

Notice that the Python Script takes the result object list x, and by calling the resultobjects’ getObjectmethod, builds a list of the actual cataloged objects (z), which itreturns instead of the list of result objects This allows the DTML to call the individ-ual objects’ absolute_urlmethod, instead of the result objects’ getURLmethod.Both approaches are valid, but there is a tradeoff The absolute_urlmethod is com-mon to all objects, making it easier to pass almost any object list to this DTML,which can make code reuse a little easier However, result objects are typicallymuch lighter weight that the actual objects they represent, which makes them (andtheir associated getURLmethod) a better choice if the list is either very long, or theobjects very large, either of which will increase the amount of memory Zoperequires to retrieve the object list

A hybrid approach can sometimes work, by having the Python Script simply returnthe result object list like this:

x = context.Catalog({‘PrincipiaSearchSource’: ‘about’})return x

In order for this to work and allow the DTML to just call absolute_url, the Catalogmust store absolute_urlas metadata for the cataloged objects This approachgives you the advantages of both DTML portability, and reducing the system load,

at the cost of increasing the amount of metadata that the ZCatalog stores

The catalog query can easily be made dynamic by using a variable name instead of

a literal (not surrounded by single quotes), in order to pass in a dynamic value, as

in the following example:

x = context.Catalog({‘PrincipiaSearchSource’: searchtext})

z = []

for y in x:

z.append(y.getObject())return z

Make sure that the Python script object has a searchtextparameter defined, andcall the Python script object from DTML, like this:

Trang 18

Accessing ZCatalogs from Python products

Accessing a ZCatalog from within a Python product is just as easy as from within ascript object, assuming that the class in question inherits from Acquisition

As you can see, the only real difference between a Python product and a Pythonscript object is how the ZCatalog is accessed initially After you access the Catalog,the Python syntax is identical

More information on writing Zope Python products is in chapters 6 through 10

Complex queries from Python

It’s possible to do more complex queries from Python than the examples we’vegiven you so far

One interesting thing you can do is pass more than one key/value pair to theZCatalog:

x = context.Catalog({‘PrincipiaSearchSource’: ‘an’, ‘id’:

Cross-Reference

Trang 19

Unfortunately, this does not produce a true Boolean OR, as the result is merely aconcatenation of the two lists, and the results that meet both requirements appeartwice We can rewrite the code to eliminate duplicates as follows:

z.append(w)for q in y:

z.append(q)return z

This is a bit cumbersome, but it gets the job done This code loops through eachresult in the first sequence x, checking it against each item in the second sequence

y(in a second loop) The code here has to check the actual cataloged objects (notthe results themselves) by retrieving them using getObject() Only if there is nomatch does the result from the first sequence get appended to the returnedsequence z Then the second sequence yis appended to the returned sequence zinit’s entirety (since it contains no duplicates with the list), which is then returned.Now the script returns a true Boolean OR of the two sets

Making Zope Product Classes auto catalogable (CatalogAwareness)

Making a Python Zope Product that automatically catalogs itself when it’s created,and reindexes itself whenever it’s changed is fairly easy and straightforward Theclass needs to subclass from CatalogAware, and it needs to call self.reindex_object()whenever the object is changed Here is the Hello Product from Chapter 6after it has been made CatalogAware:

from OFS.SimpleItem import Itemfrom Globals import Persistent, HTMLFilefrom Acquisition import Implicit

from Products.ZCatalog.CatalogPathAwareness import CatalogAwaremanage_addHelloForm = HTMLFile(‘DTML/manage_addHelloForm’, Æglobals())

def manage_addHello(self, id, REQUEST):

“Method for adding a Hello object”

newHello = helloClass(id)self._setObject(id, newHello)

Trang 20

return self.manage_main(self, REQUEST)class helloClass(Item, Persistent, Implicit, CatalogAware):

def init (self, id, Name = ‘World’):

self.id = idself.Name = Namemeta_type = “Hello Object”

manage_options = ({‘label’:’Edit’, Æ

‘action’:’manage_editHelloForm’},)def hello(self):

return “Hello, “ + self.Namedef edit(self, Name, REQUEST):

“method to edit Hello instances”

self.Name = Nameself.reindex_object()return self.index_html(self, REQUEST)

# Web Methodsindex_html = HTMLFile(‘DTML/index_html’, globals())manage_editHelloForm = Æ

HTMLFile(‘DTML/manage_editHelloForm’, globals())

As you can see, only one line needed to be added, and one other line changed, inorder to make this Class automatically Catalog itself (CatalogAware) The Class willnow automatically catalog itself with the ZCatalog (named Catalog) whenever aninstance is added (or copy-and-pasted), and automatically remove itself from theZCatalog whenever it is deleted The only thing the class needs to do itself is re-index itself when it is changed It’s worth noting that CatalogAwareness does nothook into the persistence machinery, so reindexing will not happen by itself even

if the attribute that changed was immutable You always have to triggerreindex_object()on the class instance yourself

In the preceding example, the Module is importing the CatalogAware class fromProducts.ZCatalog.CatalogPathAwareness, rather than from Products.ZCatalog

CatalogAwareness This is to take advantage of improvements made to that sion of CatalogAware that use the objects’ physical path within the ZODB touniquely identify an object, rather than use the Objects’ URL, as the previous ver-sion of CatalogAware did This avoids several problems related to virtual hostingseveral domain names on the same Zope server, and also avoids problems associ-ated with accessing the same server using different IP addresses or networknames You should always use Products.ZCatalog.CatalogPathAwareness

ver-CatalogAware to make your Zope Products ver-CatalogAware

Note

Trang 21

More about ZCatalog

There is more to the ZCatalog than automatically generating search interfaces Here

is some more in-depth information

More about text indexes

As described earlier in the chapter, a text index is used to index human-readabletext You can search the index for objects that contain certain words Text indexesalso enable you to make more advanced searches than just looking for a word.ZCatalog’s Text Index can do the following:

✦ Use Boolean query expressions such as word1 AND word2 This returns allobjects that contain both words Supported Boolean expressions include AND,

OR, and AND NOT.

✦ Control search order by grouping queries using parentheses: (word1 AND word2) AND NOT word3) This returns objects that contain both of the first twowords, but does not return any that contain the third word

✦ If your catalog contains a Globbing Vocabulary object (the default Vocabularyhas Globbing enabled), you may also use wildcards in your search queries,such as searching for Zo*to return objects that contain Zoroaster, Zope, and ZODB

More about field indexes

Unlike text indexes, which break up attributes into words that are indexed rately, a field index treats the value of an attribute as an indivisible whole, and itindexes the entire value of the attribute This makes field indexes very useful forindexing attributes whose value must be one of a limited set of choices (for exam-ple, selection properties) and for attributes whose value must be treated as awhole, such as Ids, even if they do have spaces in them

sepa-About Vocabularies

A simplistic approach to searching for a word in various objects would be to use a regularexpression to determine whether the word existed as a substring of the relevant attributes,but this would be a very resource-intensive operation and would not scale particularly well.All ZCatalog indexes are intended to minimize search times by creating lookup tables tomake the determination faster Because human-readable text passages conform to certainrules of grammar, a text index can use rules to determine in advance what substrings arelikely to be relevant, and store only those in the lookup table However, because these rulesare different for every language (and sometimes for each subject), ZCatalogs break out thisfunctionality to a separate object called a Vocabulary When you create a Text index, youmust choose which Vocabulary it uses

Trang 22

Here are some of the rules that Vocabulary objects use to determine what substrings areworth indexing:

Breaking up the text into words.In western languages, words are delimited bywhitespace or punctuation on either end of the substring In many Asian languages, sin-gle characters are considered words, or else the determination is made from context

Choosing which words to ignore.In English, there is no point in indexing wordssuch as “a,” “of,” “and,” “it,” and so on In other languages, the list of ignorablewords (called stop-words’) will be different

Indicating synonyms.In English, the words “present” and “gift” can be consideredsynonyms, and you would want a search for “gift” to also bring up objects that con-tain the word “present,” but this does not make sense in any other language

However, note that in some situations, this does not necessarily make sense inEnglish either, and “present/now” or “present/display” may make a more suitablepair for your context

Indexing the stem words only.Someone searching for the word “park” would also

be interested in occurrences of the words “parking” and “parks.” A Vocabulary usesrules to trim suffixes from words in order to make sure that the stem words only getindexed, and also trimming these suffixes from the query strings This makes surethat variants based on different tenses show up in a search However, these rulesare different from one language to another, with some languages having prefixes, oreven compound words that need to be split up further and indexed separately

When you create a Vocabulary object, you must choose which splitter to use, and whether

to make the Vocabulary object Globbing Three splitters are available: the standardZopeSplitter, an ISO-8859-1 Splitter, and a Unicode aware Splitter Globbing vocabulariesare more complex vocabularies that allow wild card searches on English text to be per-formed because they also index word fragments However, they use a lot more memoryand space in the ZODB than non-globbing vocabularies

The different splitters are intended to be used depending on the character set of the tent being indexed The standard ZopeSplitter is basically for use on objects containingASCII encoded English text, and is primarily useful for that purpose The ISO-8859-1 splitter

con-is able to recognize and index characters that lie outside the ASCII character-set, and takesits name from the standard that defines the characters in the Latin-1 character-set used bymany Western European languages such as German, French, Danish, and so forth TheUnicode splitter is intended to be used with texts encoded using the Unicode standard,which encompasses practically all known human languages

Creating a Vocabulary object is fairly simple Within a ZCatalog instance, delete the existingVocabulary object by selecting the checkbox next to it, and clicking the Delete button Next,choose Vocabulary from the drop-down list In the form that comes up, you can set the id

of the Vocabulary object (you should type in Vocabulary), the Title (which you can omit),

the type of Splitter (choose ZopeSplitter), and whether the Vocabulary object is Globbing(non-Globbing is the default, select the checkbox to make the Vocabulary Globbing)

Once you’ve made your selections, click Add, and a Vocabulary with the settings you’veselected will be added to the ZCatalog

Trang 23

By default, ZCatalogs are instantiated with three field indexes:bobobase_

modification_time, id, and meta_type The search_formDTML method that yougenerated earlier uses a text field to query the meta_typeof the objects that werecataloged, but this isn’t very useful An object’s meta_typecan only be equal to one

of a limited number of choices, so it doesn’t make sense to potentially give a wrongresult because of a mistyped query So, we are going to show you how to modifythe search interface to take advantage of the field index

Find the section in the search_formDTML method that reads as follows:

More about keyword indexes

Keyword indexes take a sequence of strings and break them up into their individualstrings and index them individually In this way, they are a little like text indexes (inthat they break up an attribute into its components) and like Field indexes (in thatthe individual strings are then treated as indivisible) As their name suggests, theyare very useful for indexing attributes that serve as sequences of keywords, whichcan then be used to place objects into categories

Typically, a keyword index would index either a line or multiple select property (in

a ZClass) or a list of strings (in a Python class) As an example, let’s say that you aretrying to categorize a collection of books in a departmental library that are listed

Trang 24

on your company Intranet You create a ZClass with author, title, and descriptionproperties, and a multiple-selection property called categoriesthat is populatedfrom another property, category_list.

In the catalog that the books will be indexed in, you create a categorieskeywordindex Now let’s suppose that you have the following categories to choose from foryour books (partial list):

under both Design and HTML, while this book (the Zope Bible) would be

catego-rized under Programming, Python, and Zope

In your search interface, you would provide a multiple selection form element, likethe following:

<select name=”categories:list” multiple>

Notice how the form uses the uniqueValuesFor()method rather than the category_

listproperty This ensures that only those categories that actually have booksassociated with them are listed as valid choices

Trang 25

More about path indexes

Path indexes take a path attribute and break it up into a sequence of successiveshorter paths by removing the object on the end of the path Thus, a DTML docu-ment located at /marketing/branding/style_guide/logos.htmlis indexed under thefollowing subpaths:

✦/marketing/branding/style_guide

✦/marketing/branding

✦/marketingSearching for any of these subpaths returns the document and any other objectsstored under the subpath The following code lists all documents stored in or underthe /marketingfolder and links to them:

<ul>

<dtml-in expr=”Catalog(meta_type=’DTML Document’, path=’/marketing’)”>

<li><a href=”&dtml-getURL;”><dtml-var title_or_id></a>

</dtml-in>

</ul>

Path indexes are particularly useful if you are using your site’s containment chy to categorize and structure the content of your site

hierar-The Advanced tab

The Advanced tab in a ZCatalog lets you perform some maintenance operations,and controls some finer details that determine how the ZCatalog operates

The Advanced tab has two sections, Catalog Maintenance and Subtransactions TheCatalog Maintenance section of the tab has two buttons on it, Update Catalog andClear Catalog The Update Catalog button is similar in its operation to selecting allthe indexes on the Indexes tab and clicking the Reindex button This clears all theindexes, and recatalogs all cataloged objects, repopulating the indexes and updat-ing the object’s metadata

Clicking the Clear Catalog button does just as its name suggests, clearing the log of all cataloged objects and metadata For all intents and purposes, the Zcatalogforgets about all the objects it has cataloged and their stored metadata It doesn’tremove the indexes you’ve set up in the ZCatalog, though it does wipe them clean.The Subtransactions section is a bit more involved It controls whether Zope com-mits cataloging transactions a little at a time, or tries to do so all at once

Trang 26

Using subtransactions reduces the amount of memory ZCatalog needs when loging large numbers of objects, but also slows the cataloging operations down Soyou’re trading memory for speed Subtransactions are enabled by default Whensubtransactions are enabled, you can disable disable them by clicking the Disablebutton When subtransactions are disabled, you can enable them by clicking theEnable button.

ZCatalog subtransactions are not compatible with ZSQL methods If you are loging objects and using ZSQL methods in the same transaction, you must disablesubtransactions in the ZCatalog

cata-When Subtransactions are enabled, you can also determine the threshold abovewhich a subtransaction will be committed The default is 10,000 objects Loweringthe number causes subtransactions to be committed more frequently, lowering thenumber of objects that need to be kept in memory at any one time during a cata-loging (or recataloging) operation, and further slows the cataloging operationdown, and increasing the number effects the reverse tradeoff, keeping more objects

in memory to speed the cataloging operation How much memory is saved or used,and how much the cataloging operations are sped up or slowed down, dependsvery much on the specifics of the objects that you’re cataloging If your objects arelarge, and you find that cataloging operations are causing your server to run out ofmemory, you can try lowering the subtransaction threshold

Summary

In this chapter, you learned how to catalog content in your Zope site in order tosearch and retrieve it quickly, based on the indexed attributes of the objects Youalso learned about storing metadata about the objects in the ZCatalog, in order tomake the search results more informative

All of the different index types were discussed, including text indexes, keywordindexes, field indexes, and path indexes, along with their uses in various contexts

We also introduced using ZCatalog queries from DTML and from within PythonScript Objects and Python Products

The ZCatalog is a very powerful tool for developing Web sites, especially when bined with CatalogAwareZClasses and Python products to automatically catalogand index a site’s content as it is added to and changed

Note

Trang 28

Zope Page Templates

In this chapter, we’ll discuss the drawbacks of DTML and

you’ll meet Zope Page Templates, a new presentation ing technology introduced in Zope 2.5 As always, we providesome references for further reading at the end of the chapter

script-The Problem with DTML

Throughout the rest of this book, we used DTML (DocumentTemplate Markup Language) for all code that is specific to thepresentation layer of our examples, and in some cases we’veshown you how to code logic in DTML as well However,DTML has some serious shortcomings:

✦ DTML tags are not friendly to HTML editors

✦ DTML source is not renderable by a WYSIWYG (WhatYou See Is What You Get) editor

✦ DTML encourages mixing of presentation and logic

To be sure, the present form of the DTML syntax was a greatimprovement over the original syntax Witness the followingequivalent pieces of code:

<! #in objectValues(‘DTML Document’) >

Nevertheless, despite these improvements, DTML still hasproblems

Trang 29

DTML tags are not friendly to HTML editors

No generally available HTML (Hypertext Markup Language) editor understandsDTML tags or knows what to do with them A few, such as Macromedia’sDreamweaver, can be set to ignore tags that they are unfamiliar with, but this doesnot necessarily let you edit the page

Suppose your code is doing something simple, such as determining which of eral background colors to use for a table cell, as in this code fragment:

sev-<td <dtml-if sequence-even>bgcolor=”#CCCCCC”<dtml-else>

bgcolor=”#FFFFCC”</dtml-if> >

Leave aside for the moment the fact that most editors will simply choke at whatthey see as a completely malformed <td>tag — an HTML editor that lets you setattributes on a tag will likely balk at what it sees as a duplicated bgcolorattribute.Some editors might even attempt to fix the code and remove the redundant bgcolorattribute

You could instead duplicate the HTML completely, like this:

<dtml-if sequence-even><td bgcolor=”#CCCCCC”>

<dtml-else><td bgcolor=”#FFFFCC”>

</dtml-if>

But now the editor will complain about opening a new table cell without closing theprevious one So you go ahead and completely duplicate the entire tag, includingwhatever DTML code was supposed to populate the cell with content Duplicatingcode is of course a recipe for a site that is difficult to maintain, and weren’t weusing Zope to avoid that in the first place?

Now you break apart your HTML into reusable pieces, and put them into their ownmethods Hmm Weren’t we already doing that with standard_html_headerandstandard_html_footer? Which brings us to the next point .

DTML Methods and Documents are not renderable by WYSIWYG editors

This is an issue only partly related to the previous one Because DTML Documents

and Methods are not complete HTML documents, a WYSIWYG editor can’t render

them in order to give an HTML designer any idea as to what it will look like

Consider the following DTML Document:

Trang 30

There is just no way that an HTML editor can interpret this as a valid HTML ment, even if it ignores the DTML tags The capability to inline and render modularcode sections is a powerful capability for application servers such as Zope, but itsimplementation in DTML (and similar server-side scripting technologies) leads topages whose HTML is scattered among various DTML Documents and Methods,with no way to edit the page as a whole.

docu-As a result, HTML designers are limited to creating HTML templates in their favoritetools, and then handing them off to developers who proceed to chop them up intoheaders, footers, navigation bars, and so on, and inserting the necessary DTMLcode to pull in data from the ZODB (Zope Object Database) to both reassemble thepieces into pages and populate the page with content

Sadly, this process is entirely one way, and the designer cannot edit the DTML-ifiedversion with his or her favorite tools, as the template is no longer in any one place

Furthermore, if the designer wants to tweak his or her design, he or she has to ate a new template and hand it off to the developers again for the whole process to

cre-be repeated This creates a lot more work for the developers that they could havebeen spending creating new functionality for the site

DTML encourages the mixing

of presentation and logic

DTML enables you to do some powerful things Unfortunately, not all of thesethings are directly related to rendering the presentation layer These include suchcapabilities as instantiating objects, deleting objects, setting cookies, redirectingthe browser, and so on

To be fair, at the time that the DTML syntax was originally created, Python code forZope was limited to filesystem-based external methods, and Python Script objectsdidn’t yet exist For any logic you wanted to add to your site through the Web, youpretty much had to use DTML Once ZODB-based Python Script objects were added

to Zope, there was less need for these capabilities within DTML, but they remain inZope for backward compatibility Unfortunately, it can be difficult to disciplineyourself and enforce the separation between presentation and logic when to a largeextent you’re using the same syntax for both

When presentation and logic are mixed together in this way, the code is much moredifficult to understand, debug, and modify Maintainability of both presentation andlogic suffer Separating the logic out into Python products, and restricting the use ofDTML to presentation only is a good practice, but product code, being on thefilesystem is more difficult to work with than through-the-Web code Python Scriptobjects (added to Zope in version 2.3) finally enabled developers to cleanly sepa-rate presentation and logic from each other and still write code through the Web,but the temptation to cross the line from presentation logic to application logicwhen working in DTML is always there

Trang 31

Clearly, an alternative to DTML that did not have these problems was called for.Enter TAL (Template Attribute Language).

While DTML has its drawbacks as a templating language for HTML pages, it is stillquite useful when you need to dynamically create other file formats such ascomma-delimited text files For this reason, and for reasons of backward compati-bility, Zope will continue to support DTML in the foreseeable future

TAL (Template Attribute Language)

In Zope 2.5, Zope is integrating a new syntax and paradigm for developing PageTemplates that avoids the problems of DTML, and introduces some interesting newcapabilities The new syntax is based on XHTML (Extensible Hypertext MarkupLanguage) attributes, which can be attached to ordinary HTML tags Following is anexample of a dynamic greeting:

<b>Hello, <span tal:replace=”user/getUserName”>UserName</span>!</b>

In this sample, an ordinary <span>tag has been augmented with an additionalattribute This is an XML namespace attribute, as indicated by the colon (:) in theattribute name The tal:replaceattribute indicates that the result of the pathexpression that it is assigned as a value should replace the entire tag that theattribute is on, giving the following rendering:

<b>Hello, Bill!</b>

Assuming, of course, that the user viewing the rendered page has a username of

“Bill.” We’ll get back to path expressions later in the chapter, as these are one of theexpression types defined by the TALES (TAL Expression Syntax)

What’s interesting here is that unlike with DTML, or practically any other ing solution, both the rendered and unrendered code are valid HTML (or XHTML),

templat-so the editor you use to create the template won’t have any more problems withthe unrendered page than the browser does with the rendered one All the editorneeds to be able to do is ignore any unfamiliar attributes and most good editors dothis very well

Page template basics

In your Root Folder, choose Page Template from the drop-down list of objects, andyou’ll see an Add Page Template form like the form shown in Figure 18-1

Type Test for the id and click Add and Edit You should now see a form like the formshown in Figure 18-2

Note

Trang 32

Figure 18-1: The Add Page Template form

Figure 18-2: The Edit Page Template form

Ngày đăng: 14/08/2014, 06:22