This document contains instructions how to manipulate Archetypes schema
(data model for content items) and fields and widgets it consists of.
Schema is list of fields associated with a content type.
Each field can belong to one schemata which corresponds to one Edit tab
sub-tab in Plone user interface.
Field schemata is chosen by setting field's
Archetypes based data model is defined as Schema object, which is a list of fields.
When your class is being constructed you can refer the schema simply in Python:
# Assume you have YourContentSchema object
You can access context schema object by using Schema() accessor.
Run-time schema patching is possible, so Schema() output might
differ what you put in to your content type during the construction.
schema = context.Schema()
Each field has accessor method. Accessor method is
- In your content type class
- Automatically generated if you don't give it manually
- Has name
get + schema field name with first letter uppercase. E.g.
yourfield has accessor method
There are a few exceptions to this rule, for fields that correspond
to Dublin Core metadata. To conform to the Dublin Core specification,
the accessor method for the
title field is
Description() for the
Archetypes has two kinds of access methods:
getSomething(), which filters output;
- raw, the so-called edit accessor,
getRawSomething() which does not
If you use direct attribute access, i.e.
obj.something you can get a BaseUnit object.
BaseUnit is an encapsulation of raw data for long text or file.
It contains information about mimetype, filename, encoding.
To get the raw value of a
BaseUnit object you can use the
method, or more simply
str(baseunit) (but take care that you don't
mess up the encoding).
You can use field.get(context) to read values of fields indirectly, without knowing the accessor method.
This example shows how to read and duplicate all values of lc object to nc:
from Products.Archetypes import public as atapi
nc = createObjectSomehow()
# List of field names which we cannot copy
do_not_copy = ["id"]
# Duplicate field data from one object to another
for field in lc.Schema().fields():
name = field.getName()
# ComputedFields are handled specially,
# and UID also
if not isinstance(field, atapi.ComputedField) and name not in do_not_copy:
value = field.getRaw(lc)
newfield = nc.Schema()[name]
# Mark creation flag to be set
field.writable() provides a short-cut whether the currently
logged in user can change the field value.
field = context.Schema()["phone_number"]
assert field.writable(), "Cannot set phone number"
There is also a verbose debugging version which will print the reason
to log if the writable condition is not effective:
field = context.Schema()["phone_number"]
assert field.writable(debug=True), "Cannot set phone number"
Below is a sample through-the-web Python Script which
you can drop to any Plone through Zope Management Interface.
Use case: People are lazy to write descriptions
(as in Dublin Core metadata). You can generate some kind
of description by taking the few first sentences of the text.
This is not perfect, but this is way better than empty description.
This script will provide one-time operation to automatically
generate content item descriptions based on their body text
by taking the first three sentences.
The script will provide logging output to standard Plone log
(var/log and stdout if Plone is run in the debug mode).
def create_automatic_description(content, text_field_name="text"):
""" Creates an automatic description from HTML body by taking three first sentences.
Takes the body text
@param content: Any Plone contentish item (they all have description)
@param text_field_name: Which schema field is used to supply the body text (may very depending on the content type)
# Body is Archetype "text" field in schema by default.
# Accessor can take the desired format as a mimetype parameter.
# The line below should trigger conversion from text/html -> text/plain automatically using portal_transforms
field = content.Schema()[text_field_name]
# Returns a Python method which you can call to get field's
# for a certain content type. This is also security aware
# and does not breach field-level security provided by Archetypes
accessor = field.getAccessor(content)
# body is UTF-8
body = accessor(mimetype="text/plain")
# Now let's take three first sentences or the whole content of body
sentences = body.split(".")
if len(sentences) > 3:
intro = ".".join(sentences[0:3])
intro += "." # Don't forget closing the last sentence
# Body text is shorter than 3 sentences
intro = body
# context is the reference of the folder where this script is run
for id, item in context.contentItems():
# Iterate through all content items (this ignores Zope objects like this script itself)
# Use RestrictedPython safe logging.
# plone_log() method is permission aware and available on any contentish object
# so we can safely use it from through-the-web scripts
context.plone_log("Fixing:" + id)
# Check that the description has never been saved (None)
# or it is empty, so we do not override a description someone has
# set before automatically or manually
desc = context.Description() # All Archetypes accessor method, returns UTF-8 encoded string
if desc is None or desc.strip() == "":
# We use the HTML of field called "text" to generate the description
# This will be printed in the browser when the script completes successfully