You are not logged in Log in Join
You are here: Home » Members » hathawsh » mywiki » SandBox

Log in
Name

Password

 
 

History for SandBox

??changed:
-
Zope 2.2 Product Developer's Guide - Chapter III - Python Products

  Approaching the Zope Product API

    Extending Zope is quite simple compared to many other
    environments. Since Zope is based on the clear, elegant Python
    scripting language, Zope extensions are quick to develop and clear
    to maintain.

    However, since they can leverage the full power of the Zope
    framework, writing a Zope Product is more complicated than the
    extremely simple extensibility of External Methods. Fortunately
    the step up in complexity is much less than the dramatic increase
    in functionality.

    In this tutorial we are going to build a poll Product.

    The included Python and DTML files show some of the steps in the
    development of a sample poll Product. The 'Poll.tar.gz' file is
    the completed Product. To install the completed Product ungzip and
    untar it inside your Zope directory. Then shutdown and restart
    Zope to start using the sample poll Product.

  What you need to know before you begin

    Before you read this tutorial you should have a basic
    understanding of how Zope publishes Python objects. You should, of
    course, know Python reasonably well. If you've used object
    publishing before, perfect. If not, you might want to read an
    introduction to object publishing before you begin, because the
    Zope Product API is just a special case of object publishing
    programming. Finally you should have a reasonable familiarity with
    Zope itself. You should understand how to do things like create
    Folders and Documents, and use DTML to call methods, and set
    properties. The Zope Manager's Guide is a good place to learn how
    to use Zope.

  Defining and analyzing your task

    Writing a Zope Product, creating a website, building a database,
    all these activities are tasks which are done to solve specific
    problems. If you want to do a good job building a solution, you
    must understand your problem first. In the next section we'll talk
    about different approaches to solving problems in Zope. However,
    its a good idea to start with a description of the problem.

    Here's a short problem description and analysis for our poll
    project.

    Requirements

      Customers manage their areas of a Zope site and want to
      provide information services. In this case, a customer
      wants to collect feedback from users regarding a certain
      topic. That is, they want to conduct a poll.

      A poll contains ballot with question with one or more
      answers. The ballot is the HTML presentation of the
      question, answers, and control elements. Users can select
      only one answer for a poll. Users can either vote in the
      poll or view the current results or both. The results at
      any time are displayed by default as text using an
      attractive out-of-the-box format. The appearance of the
      ballot should be customizable, and the ballot should be
      able to be embedded in other documents.

      Finally, a poll should allow voting by only a select group
      of users that have the correct credentials. That is,
      should be able to be private.

    Analysis

      The Poll appears to have actors of Customer, User,
      Privileged User. The Customer actor is someone able to add
      and manage Zope content. The User actor is someone with
      the Anonymous role that interacts with Zope. A Privileged
      User appears to be a non-Anonymous Zope User. This means
      that the Poll should expose some permissions for
      operations such as voting and presenting results, allowing
      the permissions to include various roles.

      The Poll has a number of crisp abstractions. A Poll
      represents all the state and behavior needed to accomplish
      the task. A Ballot appears to be Document with some DTML
      scripting in it. A Question might not be a separate
      object. Answers might be separate objects that leverage
      the normal Zope Folder interface to manage them.

  Is the Product API right for the project?

    After you have described and thought about your pojects, the next
    step is to evaluate whether your idea would work well as a
    Product, or if it could be better implemented some other way. In
    our case we would like to build a poll product like you see on
    Slashdot and many other sites.

    We could probably build it with SQL Methods and DTML without too
    much difficulty. Though this would require mucking around with the
    RDBMS whenever you wanted to create a new poll or modify an
    existing poll.

    We could probably build a simple polling facility just using DTML,
    Documents and maybe properties. Again, this approach would
    probably involve more administration hassles than we would like.

    Using a Zope Product we could provide easy manageabiliy to Zope
    users who want to create their own polls. Using a Product also
    gives us fine control over access controls, and gives us room to
    refine and develop our poll over a period of time.

    So we have a marginal case for turning our idea into a Product.
    OK, good enough let's get going.


  Getting started in plain old Python

    Now that we have decided to harness the full power of the Zope
    Framework to create a reusable Zope Product, the first thing to do
    is to write a prototype in Python. This prototype will try to
    capture the essential algorithms of our product. It will also
    allow us to test the guts of the product and make sure they are
    sound before we start confusing ourselves with exotic Zopisms.

    Here's a first cut at what a poll class might look like::

      class Poll:
          "A multiple choice poll."

          def __init__(self,question,choices):
              self.question=question
              self.choices=choices
              self.votes={}
              for choice in range(len(choices)):
                  self.votes[choice]=0

          def vote(self,choice):
              "vote for a choice"
              self.votes[choice]=self.votes[choice]+1

          def total_votes(self):
              "total number of votes cast"
              total=0
              for v in self.votes.values():
                  total=total+v
              return total

          def votes_for(self,choice):
              "number of votes cast for a given choice"
              return self.votes[choice]   

    Basically our 'Poll' object keeps track of what is going on in a
    dictionary that maps choices to numbers of votes. The 'vote'
    method actually casts a vote. 'votes' is a dictionary keyed the
    the choice index which keeps track of the number of votes for each
    choice. The 'total_votes' and 'votes_for' methods just report
    statistics about the poll.

    Of note is the fact that we haven't made any effort to keep people
    from voting more than once. There are a number of ways we could
    handle this, for example we could somehow record the identity of
    everyone who voted. Then when someone tries to vote we could look
    them up in our list of people who have voted. This approach has
    some problems since it is often difficult to reasonably identify
    someone. Let's leave this problem unresolved for now.

  Testing our initial implementation in Python

    An original purpose of Zope was to hide the publishing details and
    allow Python developers to think in terms of Python. Thus, at this
    stage let's go into Python and test what we have.

    OK, so does our first attempt at a poll work? Let's exercise it a
    little::

        def test():
            p=Poll("What's for breakfast?",["spam","eggs","toast"])
            p.vote(0) # vote for spam
            p.vote(2) # vote for toast
            p.vote(0) # vote for spam
            print p.total_votes() #returns 3
            print p.votes_for(0)  #returns 2

    You can find this code in the included 'Poll1.py' example file.
    Run it and see for yourself that it works.

    At first glance it seems pretty reasonable. Though if you try to
    vote for a non-existent choice you get an 'KeyError'. Also there's
    nothing forcing you to initialize your poll class with reasonable
    arguments. Well that's OK for now. But we may want to add some
    error handling later. Zope provides a number of error handling
    features, like automated user notification of errors, and
    transaction handling to abort transactions when uncaught
    exceptions are raised.

  Adding a user interface

    OK, now we have a semi-functional poll, let's add a user interface
    so that people can actually use it through the web. The normal
    Zopish way to do this is to use DocumentTemplate. A product can
[1131 more lines...]