Per Erik Strandberg /cv /kurser /blog

As you could see in My First Minimal Plone Content Type there is a difference in how a field is displayed when you view it and when you edit it. This difference is important but not trivial to understand so far (since we haven't looked at skins yet). Some built-in name-magic that is hard to find proper documentation of is responsible. A hint we should have learned already is "Use the source Luke" - a fancy way of saying: when in doubt look in the source code.

Since we do not want to SourceDive (another term for it used in the Net Hack community for people who cheat by reading the source code) just yet I will try to fill you up on some details.

Accessor and Mutator

In object oriented programming the concept of objects is of course central. Often an object can have subobjects as a part of it (often called members). You typically want to be able to modify these subobjects, for example in this christian code-snippet (would only work in a language like Python):

>>> import math
>>> print math.pi
3.14159265359
>>> math.pi = 3
>>> print math.pi
3

This snipped first accesses the value of pi, then change it and then accesses it again. By accessing a value an accessor is executed, often this function is called getPi (or just get in some contexts). In an archetype-context a method with a name similar to getPi is used.

When changing a value a mutator is used - typically called something like set or setPi.

In the archetypes framework there is also an accessor called something like getRawPi - there is a reason for this as we shall soon explain.

getMember and getRawMember

In this little example I would like a number entered and stored in an instance of MyMessage as a regular integer (like "42"). But when it is displayed I'd like some work to be executed on this number so that it is expressed in a more fancy way (like "four two"). Also I want to number, when edited, to be the regular number I entered. I of course need to implement my own versions of the getMember and getRawMember methods.

I guess this is the the core of this tutorial:

So we just implement our own versions of these methods and but them in our MyMessage class, making message.py look somehing like this:

# Archetypes imports
from Products.Archetypes.atapi import *

# Product imports
from Products.MyMessage.config import PROJECTNAME

# Schema definition
schema = BaseSchema.copy() + Schema((
    IntegerField('body',
              required = 1,
              ),
    ))

class MyMessage(BaseContent):
    """An Archetype for MyMessage application"""

    schema = schema
    _at_rename_after_creation = True

    def getRawBody(self):
        return self.getField('body').get(self, raw=True)

    def getBody(self):
        tmp = str(self.getField('body').get(self))

        o = ""

        for char in tmp:
            if char == '0':
                o += " zero"
            elif char == '1':
                o += " one"
            elif char == '2':
                o += " two"
            elif char == '3':
                o += " three"
            elif char == '4':
                o += " four"
            elif char == '5':
                o += " five"
            elif char == '6':
                o += " six"
            elif char == '7':
                o += " seven"
            elif char == '8':
                o += " eight"
            elif char == '9':
                o += " nine"
            else:
                o += " ????"

        return o

registerType(MyMessage, PROJECTNAME)

As you can see the only difference is the addition of getRawBody and getBody. If you worry about the self.getField('body').get(self) call you don't have to be that confused - I worry about it too [:-D] . It appears to be a call to the schema (self) in order to extract the field body (getField(body)) and the extracting the getBody-method created by the archetypes (pretty much the function we want to override (or more likely the opposite: the function we override contains this call only)).

Effects

When you create an instance of MyMessage now you will of course do the exact same thing as before: just enter the number.
http://www.pererikstrandberg.se/blog/plone/mymessage_accessor_1_new.png

Here is where the real magic is: the numbers are transformed into words when the method getBody is called. This could be useful for all kinds of stuff.
http://www.pererikstrandberg.se/blog/plone/mymessage_accessor_2_view.png

When we want to edit the message the getRawBody method is called and the number is extracted like an ordinary number - voilà:
http://www.pererikstrandberg.se/blog/plone/mymessage_accessor_3_edit.png

Mutator

There is of course a similar method for setting values: the mutator. By adding a simple setBody method you can change:

    def setBody(self, value):
        self.getField('body').set(self, int(value)+10000)

This idiotic method just adds the number you wanted to insert and then adds 10000 to it.

Addition is just as we would expect (remember that 10000 is added later):
http://www.pererikstrandberg.se/blog/plone/mymessage_mutator_1.png

Now that we view it the number has ten thousand added to it.
http://www.pererikstrandberg.se/blog/plone/mymessage_mutator_2.png

(This should only be used in combination with a reasonable getRawBody method since every time you edit the number it would get 10000 added to it.)

Download

This version of MyMessage can be downloaded here: [1]


This page belongs in Kategori Programmering.
This page is part of a series of tutorials on Plone Cms.