18. Dexterity I: Content types#
Add Volto screenshots for dexterity content type forms
In this part you will:
Learn about content types
Customize existing types
Create a content type through the web
Default and custom content types
Modifying existing content types
18.1. What is a content type?#
A content type is a kind of object that can store information and is editable by users. We have different content types to reflect the different kinds of information about which we need to collect and display information.
Pages, folders, events, news items, files (binary) and images are all content types.
It is common in developing a web site that you'll need customized versions of common content types, or perhaps even entirely new types.
Remember the requirements for our project? We wanted to be able to solicit and edit conference talks. We could use the Page content type for that purpose. But we need to make sure we collect certain bits of information about a talk and we couldn't be sure to get that information if we just asked potential presenters to create a page.
Also, we'll want to be able to display talks featuring that special information, and we'll want to be able to show collections of talks. A custom content type will be ideal.
18.2. The makings of a Plone content type#
Every Plone content type has the following parts:
A definition of fields that comprise a content type; properties of an object.
The "Factory Type Information" configures the content type in Plone, assigns it a name, additional features and available views to it.
A view is a representation of the object and the content of its fields that may be rendered in response to a request. You may have one or more views for an object. Some may be visual — intended for display as web pages — others may be intended to satisfy AJAX requests and render content in formats like JSON or XML.
18.3. Schemas, Fields and Values#
In a schema you can model fields that are used to store data. Plone automatically creates forms bases on the schemata of a content type to add and edit content.
Values of these fields are attributes on content objects.
Here is a example that shows how to access and modify these values in python:
>>> obj.title 'A Newsitem' >>> obj.description 'Some description' >>> obj.description = 'A new description' >>> obj.description 'A new description' >>> obj.image <plone.namedfile.file.NamedBlobImage object at 0x11634c320> >>> obj.image.data b'\x89PNG\r\n\x1a\n\x00\x00\x00\...'
Content types can have additional schemata. These are called behaviors. They are meant to be used across content types to add shared functionality.
One example is the ability of most content types to allow them to be excluded from the navigation.
The field is available on all types even though it is not defined in their schema.
Instead is is provided by the behavior
plone.excludefromnavigation that most content types use.
Each behavior schema can define fields. The values of these fields are again attributes on content objects.
plone.excludefromnavigation adds a attribute
exclude_from_nav to each object. The value is either
False because it is a boolean field.
18.5. Modifying existing types#
For now, we will not code anything. We will only use the Plone web interface features. If you do not have a local Plone instance installed on your machine, you can use a Plone pre-configured Heroku instance. Once deployed, create a Plone site, and perform the following steps.
Go to the control panel http://localhost:8080/Plone/@@dexterity-types
Inspect some of the existing default types.
Select the type News Item and click on Schema
Add a new field
Hot Newsof type Yes/No
In another tab, add a News Item and you'll see the new field.
Note that the only field in the schema of the News Item is the one we just added. All others are provided by behaviors.
So far the data in the new field
Hot Newsis not displayed when rendering the News Item. We'll take care of this later.
18.6. Creating content types TTW#
In this step we will create a content type called
Talk and try it out. When it's ready we will move the code from the web to the file system and into our own add-on. Later we will extend that content type.
Add new content type "Talk" and some fields for it:
Add new field "Type of talk", type "Choice". Add options: talk, keynote, training.
Add new field "Details", type "Rich Text" with a maximal length of 2000.
Add new field "Audience", type "Multiple Choice". Add options: beginner, advanced, pro.
Check the behaviors that are enabled: Dublin Core metadata, Name from title. Do we need them all?
Test the content type.
Return to the control panel http://localhost:8080/Plone/@@dexterity-types
Extend the new type: add the following fields:
"Speaker", type: "Text line"
"Email", type: "Email"
"Image", type: "Image", not required
"Speaker Biography", type: "Rich Text"
The schema you created through the web is stored as XML in the database. Here is the complete XML schema created by our actions:
1<model xmlns:lingua="http://namespaces.plone.org/supermodel/lingua" 2 xmlns:users="http://namespaces.plone.org/supermodel/users" 3 xmlns:security="http://namespaces.plone.org/supermodel/security" 4 xmlns:marshal="http://namespaces.plone.org/supermodel/marshal" 5 xmlns:form="http://namespaces.plone.org/supermodel/form" 6 xmlns="http://namespaces.plone.org/supermodel/schema"> 7 <schema> 8 <field name="type_of_talk" type="zope.schema.Choice"> 9 <description/> 10 <title>Type of talk</title> 11 <values> 12 <element>Talk</element> 13 <element>Training</element> 14 <element>Keynote</element> 15 </values> 16 </field> 17 <field name="details" type="plone.app.textfield.RichText"> 18 <description>Add a short description of the talk (max. 2000 characters)</description> 19 <max_length>2000</max_length> 20 <title>Details</title> 21 </field> 22 <field name="audience" type="zope.schema.Set"> 23 <description/> 24 <title>Audience</title> 25 <value_type type="zope.schema.Choice"> 26 <values> 27 <element>Beginner</element> 28 <element>Advanced</element> 29 <element>Professional</element> 30 </values> 31 </value_type> 32 </field> 33 <field name="speaker" type="zope.schema.TextLine"> 34 <description>Name (or names) of the speaker</description> 35 <title>Speaker</title> 36 </field> 37 <field name="email" type="plone.schema.email.Email"> 38 <description>Adress of the speaker</description> 39 <title>Email</title> 40 </field> 41 <field name="image" type="plone.namedfile.field.NamedBlobImage"> 42 <description/> 43 <required>False</required> 44 <title>Image</title> 45 </field> 46 <field name="speaker_biography" type="plone.app.textfield.RichText"> 47 <description/> 48 <max_length>1000</max_length> 49 <required>False</required> 50 <title>Speaker Biography</title> 51 </field> 52 </schema> 53</model>
It's awesome that we can do so much through the web and great for prototyping or small projects. But it's also a dead end if we want to reuse this content type in other sites.
Also, for professional development, we want to be able to use version control for our work, and we'll want to be able to add the kind of business logic that will require programming.
Instead, you'll create your new content type in your Python package. Using Python to define the schema gives us much more control (e.g. for validation and default-values).
18.7.1. Exercise 1#
Modify Pages to allow uploading an image as decoration (like News Items do).
Go to the dexterity control panel (http://localhost:8080/Plone/@@dexterity-types)
Click on Page (http://127.0.0.1:8080/Plone/dexterity-types/Document)
Select the tab Behaviors (http://127.0.0.1:8080/Plone/dexterity-types/Document/@@behaviors)
Check the box next to Lead Image and save.
The images are displayed above the title.