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

The Zope Bible phần 8 ppt

65 292 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

Tiêu đề Core Zope Components
Trường học University of Zope
Chuyên ngành Web Development
Thể loại tài liệu
Năm xuất bản 2002
Thành phố Zope City
Định dạng
Số trang 65
Dung lượng 751,56 KB

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

Nội dung

If you put the template code from the beginning of this section into a file named template.dtmland save it to the same place as where your code is then you can usethe script like this: i

Trang 1

Method Description

setBase(base) Sets the base URL for the returned document.

expireCookie(name, **kw) Causes an HTTP cookie to be removed from

an expiration date that has already passed.

Note that some clients require a path to be specified This path must exactly match the path given when creating the cookie The path can be specified as a keyword argument.

appendCookie(name, value) Returns an HTTP header that sets a cookie on

cookie-enabled browsers with a key “name”

and value (“value”) If a value for the cookie has previously been set in the response object, the new value is appended to the old one, separated by a colon.

redirect(location, lock=0) Causes a redirection without raising an error If

the “lock” keyword argument is passed with a true value, the HTTP redirect response code will not be changed even if an error occurs later in request processing (after redirect() has been called).

Create Dynamic Text with DocumentTemplates

In Chapter 4 we showed you how to create dynamic Web pages using DTML ods and documents In this section we will show you how to use and extend theunderlying class library that generates dynamic text documents based on tem-plates The examples in this section will be used to generate HTML Although DTMLisn’t limited to the use of HTML, it’s just such a natural fit that it’s almost difficult toimagine better examples So we’re going to take the path of least resistance for thissection We’ll leave it up to you, if desired, to find other uses for DTML

meth-The name of the library is DocumentTemplate It can be found under

lib/python/DocumentTemplateof your Zope installation With this library you cancreate callable template objects

Trang 2

A callable object is a Python object that implements the call hook Objectsthat implement this hook can be treated as functions within Python code.

Let’s jump right in and create one of these template objects and we’ll show you how

Once you have created an a template instance you can now call it

results = template_method(title=”This Document!”,

content=”Oh lookey, I’ve been “ + \

“dynamically generated by” +\

in while calling the template

See Chapter 4 for a reference of all the tags and what they can do

Cross-Reference

Note

Trang 3

Initializing templates with default arguments

You have already seen how a basic template is instantiated and used from the ous example Optionally a template can be instantiated with a mapping object,named arguments, or both to create a default namespace that is searched if a valuecan’t be found from the arguments that are passed in when the template is called

previ-Using the same example as previously (one you should be quite familiar with bynow!) we can change it to use some default values via named arguments

template_method = HTML(template_source, Æ{title:”Missing Title”}, content=”Missing Content”)

Now you can call the template without any arguments

template_methodas the first argument, the results would look like this:

>>> class k: pass

Trang 4

Working with templates stored in files

Instead of cluttering your source code with long format strings you can put yourtemplates into individual files In fact, this is such a convenient way of working withtemplates that the DocumentTemplate library provides a class that can be instanti-ated with a filename instead of the source of the template

If you put the template code from the beginning of this section into a file named

template.dtmland save it to the same place as where your code is then you can usethe script like this:

import syssys.path.append(“c:\\program files\\website\\lib\\python”)from DocumentTemplate import HTMLFile

template_method = HTMLFile(“template.dtml”,

title=”No Title”,content=”No Content”

)

Document template security

DocumentTemplates have basic security checks that prevent attributes that startwith the underscore from being used in templates If desired you can extend yourtemplates to perform other security checks while rendering

In the following script we subclass the HTML object and provide the guarded_ getattr()hook The hook takes two arguments (besides “self”) the object, and thename of the attribute that is being accessed in the DTML So back to the script In itwe’ve implemented the hook and check to see whether “bob” is the one attempting

to render the attribute If it is “bob,” we return the value of the attribute, if it’s body else, we raise a RunTime exception

any-import syssys.path.append(“c:\\program files\\website\\lib\\python”)from DocumentTemplate import HTML

Trang 5

There’s one other hook that you can define named gaurded_getitem() that will becalled when using mapping objects within DTML expressions Using a modified ver-sion of the preceding script we’ve defined the hook and changed the DTML used inthe template to show you how it works.

import syssys.path.append(“c:\\program files\\website\\lib\\python”)from DocumentTemplate import HTML

dict = {‘title’:’Title inside a key’}

user = raw_input(“Enter your user name: “)print template_method(dict=dict)

The key thing that we should point out in the previous example is that you had toexplicitly pass your mapping object in as a named argument This is because DTMLdoes not search mapping objects if you pass them in like an object So to getaround this, we call the function as follows, template_method(dict=dict)

Trang 6

Creating your own tags

To finish this section on DTML, we’ll show you how to create your own tags

Creating tags can lead to some exciting possibilities For instance there’s theCalendar tag (originally created by Ty Sarna, now maintained by the Zope commu-nity, and available at http://www.zope.org/Members/jdavid/Calendar) that renders

an HTML representation of a calendar This is great way to generate a dynamic endar with little HTML coding effort

cal-We’re not going to create anything so complex in this chapter, but we will show youthe basics of creating tags so that, if you like, you can impress the world with thenext innovative tag

There are two types of tags that can be created: block and singleton tags Block tags

are two-part tags that consist of an opening and a closing tag Examples of thesetags are the inand iftags The other type of tag is the singleton tag, such as the var

and the calltags that don’t have a closing counterpart

Creating a tag is a simple matter of implementing all of the required interfaces andregistering it as an available command We’ll start with the singleton tag

Creating a simple singleton tag

We’ll start with the equivalent of a hello world example, and then show how tomake more complicated aspects of tags like using arguments and expressions, andworking with values from a templates namespace

Here’s the most basic of tags that simply inserts the phrase “Hi Mom!” when dered It can be used in a template by inserting <dtml-himom>into a templatessource Singleton tags need to implement three things in their class:

ren-✦ A nameattribute, which is used to match your class to the tag when it is used

in a template For instance in the example that follows, we set name equal to

“himom”.

✦ A constructor ( init ) method that takes one attribute called “args.” Fornow we’ll pass on this method since we don’t need it for our first example

✦ A render()method, which is hook that is called by the template when the tag

is rendered This hook needs to take one argument, usually called “md,” which

is a TemplateDictionary (your guess is as good as ours as to why it’s calledmd) The Method Dictionary is the namespace passed to the template We’llignore the TemplateDictionary for now since we’re only going to insert the “HiMom!” phrase

Without further ado here’s a Python script that creates our “himom” tag, registers

it, and then builds a sample template to test it:

import syssys.path.append(“c:\\program files\\website\\lib\\python”)from DocumentTemplate.DT_String import String

Trang 7

# Create a class for our tagclass HiMomTag:

name = ‘himom’

def init (self, args):

passdef render(self, md):

return “Hi Mom!”

call = render

# Register our new tag so we can use it in a templateString.commands[‘himom’] = HiMomTag

# Test it out by creating a template

from DocumentTemplate import HTMLtemplate_src = “<dtml-himom>”

template_method = HTML(template_src)print template_method()

If you save all this code into file and run it with Python, it will produce the followingresults:

Hi Mom!

Using arguments in tags

Let’s put the “Dynamic” in DTML by using arguments in your tag so that you caninsert a message to your mother

It’s now time to talk about a tag’s constructor It’s important to note that your tag’s

init method is only called when the template is instantiated In other wordswhen you run the following code:

template_method =HTML(template_source)

When this happens the tag class is passed its argsas a string You need to parsethe string and set the appropriate attributes on your tag instance so that you canuse the values when the tag is rendered later The value of argsis everythingbetween the beginning and end of the tag (<dtml-nameand >) For example if yourtemplate’s source contained:

<dtml-himom msg=”the dogs dead.” btw=”Oh, and I won’t be home for dinner!”>

then the value of argswill be equal to msg=”the dogs dead.” btw=”Oh, and I won’t

be home for dinner!” You could attempt to parse this string yourself (if you’re a masochist) or you coulduse a handy method provided as part of the DocumentTemplate library called

Trang 8

parsed_params() This method takes a string as its first argument, and then a series

of named arguments that specify what values should be present in the argsstringand what they should default to if not present Knowing this, we can update are tag

to parse the argswhen the object is instantiated and modify our tag’s rendermethod to use the attributes if they’re present

import syssys.path.append(“c:\\program files\\website\\lib\\python”)from DocumentTemplate.DT_String import String

from DocumentTemplate.DT_Util import parse_params

# Create a class for our tagclass HiMomTag:

name = ‘himom’

def init (self, args):

args = parse_params(args,msg=””,

btw=””)self.msg = args[‘msg’]

template_method = HTML(template_src)print template_method()

Running this script we get:

Hi Mom, the dog’s dead Oh, and I won’t be home for dinner!

Getting values and rendering Python expressions

All right you got us The last example wasn’t very dynamic because it was based onthe values directly inserted into the templates source To make it truly dynamic wewant to interact with those values that you pass to the template when you render it(or use the defaults)

Trang 9

This is done using the mdparameter of your tag’s render method This dictionary is

an aggregated representation of all the namespaces passed to the template when it

is rendered Imagine calling a Template Method and passing it an object thatexpects to insert the value for “title” into a document it’s creating To get this valuefrom within the render method of your tag you would simply write:

results = template_method(title=”The title”)

One other thing that you’d likely want to do is evaluate a Python expression (thesame way the vartag does) using values that are part of the template_method Youcan accomplish this with the help of the Evalclass, which provides a method forsafely evaluating Python expressions while working with the md The Evalclass willfollow all the security precautions that DTML follows, even the custom ones youprovide

To use the Evalclass import it from the DT_Utilmodule that’s inside theDocumentTemplate library Then instantiate an Eval instance with your pythonexpression This instance has a method named “eval” that returns the results ofyour Python expression using a TemplateDictionary

We’ve taken the himom example as far as we can so to demonstrate using valuesand expressions in a template Let’s build a tag that can print out a pretty version ofPython’s types

import syssys.path.append(“c:\\program files\\website\\lib\\python”)from DocumentTemplate.DT_String import String

from DocumentTemplate.DT_Util import parse_params, Eval,html_quote

#from pprint import PrettyPrentimport pprint

# Create a class for our tagclass PPrintTag:

name = ‘pprint’

Trang 10

def init (self, args):

get = parse_params(args,name=None,

expr=None).getself.name = get(‘name’)

self.expr = get(‘expr’)

if self.expr is not None:

self.expr = Eval(self.expr).evaldef render(self, md):print template_method(o)

if self.name is not None:

ret = md[self.name]

else:

ret = self.expr(md)ret = pprint.pformat(ret)return html_quote(ret) call = render

# Register our new tag so we can use it in a templateString.commands[PPrintTag.name] = PPrintTag

# An example that inserts a title attribut into

# a documentfrom DocumentTemplate import HTMLtemplate_src=”””<dtml-pprint name=”title”>”””

template_method = HTML(template_src)class k: pass

o = k()o.title = “I’m a title”

print template_method(o)

# Here’s an exampl using an expresiontemplate_src = “””<dtml-pprint expr=”x+ 20”>”””

o.x = 10template_method = HTML(template_src)print template_method(o)

Block tags

Block tags have an opening and closing tag that usually surround data and othertags In the previous example we showed you how to create a tag whose attributesuse Python expressions What expressions can’t do is evaluate tags, whereas blocktags can

Trang 11

To create a block tag, define an attribute at the class level named

“blockContinuations” and set it to an empty tuple This tells the DocumentTemplatelibrary that this is a block tag This attribute is also used to let the

DocumentTemplate library know what other special tags there are that can existonly within the opening and closing of this block tag We’ll explain more about this

in a moment

So for now, here’s an example of a note tag that produces the HTML equivalent of ayellow sticky note

import syssys.path.append(“c:\\program files\\website\\lib\\python”)from DocumentTemplate.DT_String import String

self.note = blocks[0][2]

def render(self, md):

note = self.note(md)return note_format % note call = render

# Register the tagString.commands[NoteTag.name] = NoteTagfrom DocumentTemplate import HTMLtemplate_src=”””<dtml-note>My first note!</dtml-note>”””

template_method = HTML(template_src)print template_method()

Running this script produces the following HTML:

<table border=1 bgcolor=”#FFFE7B” width=”250” height=”250”>

<tr height=10><td valign=”top”>Note:</td></tr>

<tr><td valign=”top”>My first note!</td></tr>

</table>

Trang 12

The biggest difference between a block tag and a singleton tag is in the constructor.Instead of taking a single string argument, it takes a two-dimensional list, named

“blocks.” Each item in the list represents a block in the tag Each block has threeelements:

✦ The first element is the name of the tag

✦ The second element is the argument string for the block It’s in the same mat as the argument string that is passed to the singleton constructor

for-✦ The third element is a template method, the same type that you create whenyou make a method with the HTML class This method was built using thesource of all the text that was in between the <dtml-note>and </dtml-note>

tags

Block tags can have speacil tags that are only allowed inside of the block tag Agood example of this is the <dtml-else>tag that is only allowed between a <dtml- if>and </dtml-if>tag To tell the DocumentTemplate library that your block taghas one of these special tags you add its name to the blockContinuationtuple ofyour tag’s class

The following code has been modified so that your note tag can have a subject and

a body block The subject will be all the text between the <dtml-note>and body>tag The body will be everything between the <dtml-body>and </dtml-note>

<dtml-tags If the <dtml-body>tag doesn’t exist then there will be no subject

import syssys.path.append(“c:\\program files\\website\\lib\\python”)from DocumentTemplate.DT_String import String

# Create a class for our tagnote_format = “””

<table border=1 bgcolor=”#FFFE7B” width=”250” height=”250”>

Trang 13

self.header = blocks[0][2]

del blocks[0]

else:

self.header = Noneself.note = blocks[0][2]

def render(self, md):

if self.header is not None:

header = self.header(md)else:

header = “”

note = self.note(md)return note_format % (header, note) call = render

# Register the tagString.commands[NoteTag.name] = NoteTagfrom DocumentTemplate import HTMLtemplate_src=”””<dtml-note>Read This<dtml-body>I have written asecond note!</dtml-note>”””

template_method = HTML(template_src)print template_method()

Trang 15

Scripting Zope

In previous chapters, you learned about DTML, a simple but

powerful method of creating dynamic content, andProducts, a more complex and thorough way of writing appli-cations in Zope to handle business logic Sometimes, however,

a problem is too large to be handled elegantly in a DTML ument, yet not quite large enough to warrant building anentire application around it Sometimes, all you really want isthe ability to write a small chunk of code to do something thatwould otherwise be cumbersome in DTML This is where

doc-scripts come in.

Consider the following problem Suppose you have an area ofyour Web site that needs to display the directory hierarchy upuntil the point of the page you are on, with each level being alink to that level This would give you an effect similar to theobject listing at the top of the management interfaces editingscreens, a sort of “breadcrumbs” trail leading you from thetop of your structure to where you currently are You start bygetting the folder that the document being viewed is in; thenyou get each parent of that object until you reach the Zopeapplication or some arbitrary stopping point After you haveall of the objects, you take each one in turn and build a URLfor it and join them all together for displaying If youattempted to do this in DTML, you’d have a host of unwieldypieces of code What you really want is to be able to hand thistask off to a small program written in Python Simply pass it

an object and it returns a series of URLs To do that, you use ascript

Zope comes bundled with two powerful scripting solutions:

Python Scripts and External Methods A third option, PerlScripts, is available as an add-on product

Under the hood of aPython script

Calling Python-basedscripts

External methods

Perl-based scripts

Trang 16

Jumping in with Python Scripts

The following sections assume at least a rudimentary knowledge of the Python guage Please see Chapter 5 for a primer

lan-Creating a Python-based script

To create a Python-based script, select Script (Python) from the Add menu in themanagement interface Enter an id and click Add and Edit You’re presented with anediting screen like the one shown in Figure 15-1

Figure 15-1: Editing a Python script

The Parameter List is just like the parameter list in a normal Python method It is acomma-separated list of variables to be passed into the function Default values arespecified with the syntax <parameter>=<value> Ways of passing arguments to thesescripts will be described in more detail later

The large text area is the body of the script and is where the actual Python code isplaced Almost anything you can do in a normal Python method can be done here

A few restrictions are explained later in this chapter

When you first create a Python Script, it contains some example code that strates several useful functions Let’s take a moment to examine these before youmove on to one of your own

Trang 17

demon-# Example code:

# Import a standard function, and get the HTML request and response objects.

from Products.PythonScripts.standard import html_quote request = container.REQUEST

RESPONSE = request.RESPONSE

# Return a string identifying this script.

print “This is the”, script.meta_type, ‘“%s”’ % script.getId(),

if script.title:

print “(%s)” % html_quote(script.title), print “in”, container.absolute_url()

return printed

The first thing the script does is to import a function from a module inProducts.PythonScripts.standard This module provides access to several usefulfunctions for use in Python Scripts and can be examined in closer detail by opening

up the standard.py file located in your Products/PythonScripts directory This ticular function, html_quote, converts characters that have special meaning inHTML to special syntax that can be displayed without being interpreted The nextthing we do is get the REQUEST object from the scripts container This is a usefulshortcut that can be used in place of passing the REQUEST to the script as an argument

par-See “Calling scripts” later in this chapter for more information on passing ters to scripts

parame-Notice that the script is actually printing values Unlike a Python module run fromthe command line, or code run through Python’s interactive shell, the valuesprinted here don’t go to the terminal where you started Zope Instead, they are putinto a special variable called printedthat this script eventually returns This can be

a useful tool for returning complicated, formatted output to a calling object, or even

to print out an entire HTML page, although we don’t recommend doing that

As a final note, you’ll see that the code uses a variable called scriptand accessesseveral properties This is a special bound variable and is explained in greaterdetail later on in this chapter under the section “Binding variables.”

Now let’s create a small script, the classic “Hello world!” Create a Script (Python)object with an id of helloand edit it If the script has code in it already, go aheadand erase it Fill out the fields as shown in Figure 15-2 and save

To test your script, simply click the Test tab at the top of the form You should get ascreen with the text “Hello World!”on it Easy as that!

But the script doesn’t do much good if you can’t pass it a parameter Edit the scriptagain to be like the one shown in Figure 15-3 Notice that we added a parameter tothe script and supplied a default value of World This means you can pass in thename that you would like the script to greet, but you may optionally leave it out

Cross-Reference

Trang 18

and the default value of Worldwill be used Click the Test tab again This time, younotice that it brings up a screen with an input box for the name parameter we speci-fied Go ahead and enter your name and click the Run Script button It should sayhello to you now! Try it again without the parameter and verify that the defaultworks.

Figure 15-2: A simple script

Figure 15-3: Passing parameters

Trang 19

ArithmeticError AssertionError AttributeError EOFError EnvironmentError FloatingPointError IOError

ImportError IndexError KeyError LookupError NameError None OSError OverflowError RuntimeError StandardError SyntaxError

TypeError ValueError ZeroDivisionError abs

apply callable chr cmp complex delattr divmod filter float getattr hasattr hash hex int

isinstance issubclass len list long map max min oct ord pow range repr round setattr str tuple

Most of these functions behave as you would expect them to in normal Python

However, rangeand poware limited from producing overly large numbers andsequences Of the missing functions, most deal with the filesystem (open, for exam-ple) or have the capability to affect the Zope process (such as exit)

In addition to the standard built-ins, Zope also provides a few bonus built-ins

DateTime, test, namespaceand renderare DTML utility functions And to make up

Trang 20

for removing the typefunction from the built-ins, Zope provides an alternative,

same_type, which enables you to compare the type of two objects in much the sameway as type

Besides restrictions to standard built-ins, Zope also restricts what you may importinto your scripts Python-based scripts have access to only the following modules:

Products.PythonScripts.standard, AccessControl, string, random, and math Zopealso monitors scripts for excessive looping and raises an error if it detects a potentialinfinite loop This is to prevent a Python-based script from monopolizing CPU timeand possibly reducing performance of the rest of the server or even locking it up

And, finally, like all objects in Zope, Python-based scripts adhere to the standardsecurity policies The scripts themselves cannot access objects that the user call-ing the script does not have access to unless a Proxy Role has been placed on thescript Also, as in DTML, Python-based scripts cannot access variables whosenames begin with an underscore Zope considers these private and raises an error

if you attempt it

Binding variables

You notice an area between the Parameter List and the body of the script labeledBound Names with a list of variables These are hooks back into Zope’s framework,giving you access to traversal and other useful information Click the Bindings tab of the management interface You should get a screen like the one shown inFigure 15-4

Figure 15-4: The Bindings screen

Trang 21

When you create a Python-based script, Zope automatically creates default valuesfor four of the five available bound variables Here is a list of the variables and whatthey are used for:

✦ Context This is the object on which the script is called Usually, this is the

same as the Container, but as we learned in the section about Acquisition inChapter 14, through the trickeries of Traversal, we can essentially make anyscript, anywhere, be called on any other object in the Zope Hierarchy Thedefault value for this variable is context

✦ Container This is the actual container (usually a Zope folder) where the

script resides This is useful for calling other methods stored in the samefolder The default value is container

✦ Script This refers to the script object itself and defaults to script

✦ Namespace By default, this variable is left blank, but its recommended value

is an underscore character If this script is called from DTML, this variable isset to be the namespace of the caller Normally, a script searches for itsparameters in the REQUESTobject if no parameters are passed in (see “Callingscripts from DTML,” later in this chapter.) If this variable is set, it insteadsearches through the namespace (eventually getting to the request object)

✦ Subpath If this script was traversed to in a URL, Subpath contains all the

ele-ments of the URL that occur after the script If a script named some-scriptwascalled in the URL /foo/some-script/bar/spam, Subpath would be a list contain-ing the strings barand spam This variable defaults to traverse_subpath

A simple script probably won’t use any of these variables, but they can come invery handy for more complex problems They’re also quite helpful for debuggingyour scripts

Under the Hood of a Python Script

A Zope Python script is, in essence, a Python method defined through Zope Zopetakes the parameters and body you supply and converts it into a callable pythonmethod, which runs just like you would expect it to A lot of trickery is involvedbehind the scenes in order to get your function to be called on the right object andobey Zope’s security restrictions, but if you think of it as a normal python methodwith limited access, you’ll do fine

Calling Python-Based Scripts

You can call a Python-based script just like you would any other object in Zope Thetwo primary methods are, of course, calling it from inside of another Zope object(including other scripts and DTML methods), and calling it directly via a URL Formost Zope Web applications, the former will probably be the most used way

Trang 22

However, for advanced functions, usually where another client that understandsHTTP wants to talk to your server, calling a script from the URL can be a powerfultool We’ll look at both of these methods in the following sections.

Calling scripts from DTML

Calling your scripts from inside DTML is done in much the same way as you wouldcall a DTML method If you just need to run the code but aren’t interested in dis-playing any returned results, simply use the dtml-callsyntax To display thereturned results, use the dtml-varsyntax It becomes interesting when you mustdecide how to pass parameters to your scripts

Parameters can be passed two ways, explicitly or implicitly Explicitly passing one

or more parameters to a script requires you to treat it exactly as you would a mal python function call Suppose you had a Python-based script called retrieve CustomerInfothat took the parameter customerId, processed some information, didsome formatting, and returned some information about that customer Now sup-pose you had a DTML document that looped through a list of customerIdand dis-played their information It would probably look something like this:

nor-<dtml-in customerIds>

<dtml-var item’])”><BR>

expr=”retrieveCustomerInfo(customerId=_[‘sequence-</dtml-in>

Simple enough, right? But there are shortcuts — ways to get your parameters to bepassed without explicitly specifying them If you don’t pass any parameters to ascript that requires one or more, Zope examines the REQUESTobject to see if it canfind the required parameters there This behavior also works if you have a formthat submits directly to a Python-based script Any form variables that matchparameters of the script will be matched up Any form variables that don’t have acounterpart in the Parameter List will be ignored and unavailable in the script

As mentioned earlier, if the Namespacevariable is bound, the script also attempts tofind the needed variables in calling objects Namespace These are usually otherobjects, such as a folder

See Chapter 4 for details about Zope’s Namespaceand what might be foundthere

Let’s test this out using our Hello World script created earlier in the chapter Create

a DTML Document called helloDoc in the same folder as your script with the ing bit of code in its body:

follow-<dtml-var expr=”hello(name=’John’)”>

Now view the page You should see the value returned by the script displayed Younotice that the name ‘John’was passed explicitly to the script Now let’s alter it alittle bit Change your page to look like the following:

Cross-Reference

Trang 23

<dtml-call “REQUEST.set(‘name’, ‘John’)”>

<dtml-var hello>

View the page again You now see that even though we didn’t explicitly pass theparameter namein, Zope searched the request and matched the value up anyway

Now, let’s do one final example to make it all a bit more interactive Here we create

a form that enables a user to input the name to be passed to the script We also use

a common programming technique of having the form post back to itself and dealwith the displaying of the results Edit helloDoc to contain the following code:

<form action=”./” method=”POST”>

Name: <input type=”text” name=”name” value=””>

<input type=”submit” value=”Submit”>

Note that we could have changed the action of the form to submit directly to thehello script, but the results would not have been formatted with your header andfooter There are times when this may not be such a bad thing — for example, ifyou call a RESPONSE.redirect() at the end of the script But in general, you’ll still

be calling it from another object

Calling scripts from a URL

Navigating to a script via URL is fairly simple The interesting thing is that you canchange the Context that a script is called in, and thus the object that it is called on,via the intricacies of Zope’s acquisition framework Suppose you have a directorystructure similar to the one in the following list:

Trang 24

To call the Waterscript on the ficusobject, you would call /plants/tasks/

ficus/water Because of the way Zope does Acquisition, it is able to properly findall the objects in the URL, and because of the way we’ve called our script, the con-text that wateroperates in is the ficusobject To call feedon the dogswould behandled the same way by calling /animals/tasks/feed/dogs

For more information on acquisition, see Chapter 14

A practical example

Let’s take our breadcrumbs example from the beginning of the chapter and actuallyimplement it Create a Python script called breadcrumbswith the following code inthe body:

# Take the object that this script is called on (the context)

# and traverse up to the root, getting the ID of each object.object = context

path = [] # A list of id’s, one for each object

while 1:

# The root application doesn’t have an ID attribute, instead it

# has a method that returns the id So we check to see if the

# objects id is a method or a string If it is a method we’ve

# reached the top of our trail

if same_type(object.id, ‘’):

path.append(object.id)object = object.aq_parent # Get the parent of this objectand loop

else:

break

# Because we started at the bottom and went up, we’ll

# want to reverse the order of the trail so that the

# first item is at the top most object

path.reverse()

# Since we didn’t include the root object in our list of

# breadcrumbs we’ll want to prepopulate it

breadcrumbs = “<a href=’/’>/</a>”

for i in range(0, len(path)):

Cross-Reference

Trang 25

Now, edit your standard_html_headerto include the following code somewherebelow the body:

<dtml-var breadcrumbs><BR>

Create a directory structure a few layers deep with an index_htmlthat includes the

standard_html_headerin each one View the page at the bottom of the tree Youshould see a page similar to the one shown in Figure 15-5 Each link at the topshould take you back to the particular directory as named

Figure 15-5: Breadcrumbs

External Methods

Zope provides another method of scripting with Python, that of External Methods

They’re called External Methods because the code that you write lies outside of theZODB and instead resides in the filesystem An external method is simply a method,written in Python, whose module is in the /Extensionsfolder of the Zope installa-tion To create one, you need access to the filesystem directly, or at least enough toFTP/SCP your file to the appropriate location

Open up an editor and create a file called Hello.pywith the following contents:

def helloMethod(name=”World”):

return “Hello %s!” % name

Save the file to the /Extensionsdirectory under your Zope installation If you don’thave access to the filesystem where your Zope installation is running, you need totalk to your system administrator

Trang 26

After the module is on the filesystem, you need to create a Zope External Method

object From the Zope Add menu, select External Method Enter externalHello for the Id, Hello for the Module Name, and helloMethod for the Function Name Click

add You should now have a Zope object called externalHello You can call thisfrom DTML or traverse it from the Web just like you would a normal Python-basedscript It behaves in much the same way

Why external methods?

So, the big question is, why would you want to go through all the trouble of anExternal Method when you could just create a Python-based script? As we saw inthe previous section, Python-based scripts are powerful, but they are also limited Ifyou have a particular module you want to import, chances are it won’t be available

in a simple Python-based script External methods have far fewer restrictions Withthem, you can access arbitrary packages, the filesystem, or the network This less-ening of security in the script itself is offset by the fact that you must have access

to the filesystem

A practical example

In order to perform the following example, you need access to an FTP server If youdon’t have access to one, you can use Zope’s built-in FTP server to upload the file

to the root of your Zope instance

Suppose that each day you need to upload some data via FTP to a remote server.The file is a simple comma-delimited text file created from some data pulled from aSQL database and formatted in a python script The exact contents are unimpor-tant, as long as it’s a simple text file

Open up a text editor and create a file called dailyUpload.pythat looks like the lowing, replacing the values for HOST, PORT, USER, and PASSWORD with your FTPinformation:

fol-from ftplib import FTPfrom StringIO import StringIOfrom string import joinfrom DateTime import DateTime

# Replace the contents of the following

# variables with your own FTP values

HOST = ‘##Your FTP Server##’

PORT = ‘##The Port it connects to Blank for default##’

USER = ‘##User name##’

PASSWORD = ‘##Password##’

Trang 27

def ftpData(self, data):

# Create the file object from the string data suppliedfile = StringIO(data)

# Next, login to the FTP server

ftp = FTP()ftp.connect(HOST, PORT)ftp.login(USER, PASSWORD)

# DateStamp the data then upload it

date = DateTime()dateStamp = join([str(date.year()),

str(date.month()),str(date.day())], ‘-’)filename = ‘file_%s’ % dateStamp

command = “STOR %s” % filenameftp.storlines(command, file)

# Logoutftp.close()

Place the file in the /Extensionsdirectory of your Zope installation Now create anExternal Method object with an id of dailyUpload, a module name of dailyUpload,and a Function name of ftpData Create a simple text file in your editor and upload

it to a File object called datain the same directory as your External Method Thecontents don’t matter Now create a Python script like the one shown in Figure 15-6

Figure 15-6: uploadData script

Trang 28

Test the script and then log in to your FTP server to verify that the data was cessfully transferred.

suc-Changes to External Methods are not immediately available to Zope If you edit thecode of an External Method, you need to edit Zopes External Method object.Restarting the server will also refresh the code

Perl-Based Scripts

Because Zope is itself written in Python, it’s relatively easy to provide Python-basedScripts and External Methods But for all its power, Python just doesn’t do somethings as well as other languages Perl is a powerful language, similar to Python,that many Web developers are already familiar with As such, there are Perl ver-sions of both the Zope embedded scripts and External methods

This section assumes you are installing in a Linux environment

Unlike Python scripts, Perl scripts don’t yet have the restrictions that limit theamount of Memory or CPU time taken up by them As such, it’s possible for some-one to write a Perl script that will monopolize server time and could bring yourZope installation to a halt

Before installing Script (Perl)

Before you can install Perl-based scripts, you need to make sure that Perl isinstalled Installing Perl is beyond the scope of this book, but the rest of the setuprequires that you have at least Perl 5.6.0 installed You can get Perl from theComprehensive Perl Archive Network at www.cpan.org

Perl needs to be compiled with Multi Threading support Most binary distributionsare compiled without threads This means you will probably have to install andcompile it from source For the CPAN source version, make sure you run Configurewith the -Dusethreadsflag

After Perl is installed, you need to install the pyperlmodule In a nutshell, thisenables you to embed Perl inside of Python None of it is Zope specific, but it isneeded by the Zoperl product later on Pyperl and Zoperl can both be downloadedfrom http://downloads.activestate.com//Zope-Perl/.

Note

Caution Note Note

Trang 31

While Zope comes with a rich variety of built-in object

types such as Images, Files, Documents, Folders, andMethods, occasionally you may need to define a new objecttype that will work within Zope

New object types are defined within Products There are twoways to define new object types within Zope:

✦ File system–based Python Products

✦ Through-the-Web Products using ZClassesPython product development is covered extensively in Part II

of this book In this chapter, we explain when and how to useZClasses to define new object types

What are ZClasses? OOP and Classes

In standard OOP (object-oriented programming) parlance, a

class is a blueprint or prototype that defines the variables and

the methods common to all objects of a certain kind, which

are also known as instances of the class.

So, all Folder objects within Zope are really instances of theFolder class Everything about how Folders behave is definedwithin that class For example, the functionality that enablesFolders to contain other objects and list the objects withinthem

However, not all folders are identical Folders can contain ferent objects and they can have different properties Theseattributes are not defined in the class, which is only con-cerned with those things that instances have in common

ZClasses andproperty sheets

Automaticallygenerating ZClassviews

Creating simpleapplications usingZClasses

ZClasses and security

CreatingCatalogAwareZClasses

Subclassing ZClassesfrom Python baseclasses

Distributing ZClassproducts

Trang 32

lan-a Python Product for Zope Therefore, Zope hlan-as lan-a wlan-ay for users to define new

object types through the Web by creating what are called ZClasses.

ZClasses enable you to create Products and new object types (classes) entirelythrough the Web, without resorting to creating files on the file system

ZClass-based products can be redistributed to other Zope users, and can generally

be modified after they’ve been installed if the user has management privileges onthe Root Folder, unless the developer has chosen to disallow such modification

It’s expected that in future versions of Zope, the distinction between file based products and through-the-Web products will diminish, or even disappear, butfor the moment, ZClasses and Python Products are still distinct

system-Creating a Simple ZClass

In this section, we show you step-by-step how to create a simple ZClass All of theinteresting parts will happen inside the special Products folder, which is in theControl_Panel, as you can see in Figure 16-1

As you can see, the Products folder contains a number of listings If you haven’tadded or created any through-the-Web products to your Zope installation yet, thenall of the products are indicated by “closed box” icons As we shall soon see,through-the-Web products have “open box” icons

Ngày đăng: 14/08/2014, 01:20

TỪ KHÓA LIÊN QUAN