12. Content types II: Talk#
In this part you will create a content type "Talk" to store all the data required for a talk.
Tools and techniques covered:
Registration and configuration of content types
Schema
Fields
Widgets
Check out mastering-plone-project at tag initial:
git checkout initial
The code at the end of the chapter:
git checkout talks
More info in The code for the training
12.1. The type registration#
Edit the file backend/src/ploneconf/site/profiles/default/types.xml and add the talk object.
<?xml version="1.0" encoding="utf-8"?>
<object meta_type="Plone Types Tool"
name="portal_types"
>
<object meta_type="Dexterity FTI"
name="talk"
/>
</object>
Plone will now expect a file backend/src/ploneconf/site/profiles/default/types/talk.xml and will register that as a new content type.
12.2. The FTI#
Add the file backend/src/ploneconf/site/profiles/default/types/talk.xml.
Note there is a file types.xml and a folder types.
This is the Factory Type Information that holds the configuration for the content type Talk.
1<?xml version="1.0" encoding="utf-8"?>
2<object xmlns:i18n="http://xml.zope.org/namespaces/i18n"
3 meta_type="Dexterity FTI"
4 name="talk"
5 i18n:domain="plone"
6>
7 <property name="title"
8 i18n:translate=""
9 >Talk</property>
10 <property name="description"
11 i18n:translate=""
12 />
13 <property name="icon_expr">string:${portal_url}/document_icon.png</property>
14 <property name="factory">talk</property>
15 <property name="add_view_expr">string:${folder_url}/++add++talk</property>
16 <property name="link_target" />
17 <property name="immediate_view">view</property>
18 <property name="global_allow">True</property>
19 <property name="filter_content_types">True</property>
20 <property name="allowed_content_types" />
21 <property name="allow_discussion">False</property>
22 <property name="default_view">view</property>
23 <property name="view_methods">
24 <element value="view" />
25 </property>
26 <property name="default_view_fallback">False</property>
27 <property name="add_permission">cmf.AddPortalContent</property>
28 <property name="klass">ploneconf.site.content.talk.Talk</property>
29 <property name="schema">ploneconf.site.content.talk.ITalk</property>
30 <property name="behaviors">
31 <element value="plone.dublincore" />
32 <element value="plone.namefromtitle" />
33 <element value="plone.versioning" />
34 </property>
35 <property name="model_source" />
36 <property name="model_file" />
37 <property name="schema_policy">dexterity</property>
38 <alias from="(Default)"
39 to="(dynamic view)"
40 />
41 <alias from="edit"
42 to="@@edit"
43 />
44 <alias from="sharing"
45 to="@@sharing"
46 />
47 <alias from="view"
48 to="(selected layout)"
49 />
50 <action action_id="view"
51 category="object"
52 condition_expr=""
53 description=""
54 icon_expr=""
55 link_target=""
56 title="View"
57 url_expr="string:${object_url}"
58 visible="True"
59 >
60 <permission value="View" />
61 </action>
62 <action action_id="edit"
63 category="object"
64 condition_expr=""
65 description=""
66 icon_expr=""
67 link_target=""
68 title="Edit"
69 url_expr="string:${object_url}/edit"
70 visible="True"
71 >
72 <permission value="Modify portal content" />
73 </action>
74</object>
Now our package has a new configuration for Generic Setup.
Generic Setup loads a lot of different types of configuration for the site from the folder profiles/.
This configuration is applied to your site upon installing the package.
This also means that you will need to re-install the package once we are finished with the talk.
But the type is not yet complete since the schema (ploneconf.site.content.talk.ITalk) and the class (ploneconf.site.content.talk.Talk) that are referenced in the FTI are not yet there.
12.3. The schema#
The schema holds the definition of the fields that the content type will offer to store data.
It is also the place where you would add widget options per field to control the display of fields.
In the FTI we referenced the Python path ploneconf.site.content.talk.ITalk.
The package ploneconf.site.content already exists.
Find it in at this path: backend/src/ploneconf/site/content.
In this folder add a new file talk.py with the following content:
1from plone import schema
2from plone.app.textfield import RichText
3from plone.autoform import directives
4from plone.dexterity.content import Container
5from plone.namedfile.field import NamedBlobImage
6from plone.schema.email import Email
7from plone.supermodel import model
8from z3c.form.browser.checkbox import CheckBoxFieldWidget
9from z3c.form.browser.radio import RadioFieldWidget
10from zope.interface import implementer
11
12
13class ITalk(model.Schema):
14 """Dexterity schema for Talks"""
15
16 directives.widget(type_of_talk=RadioFieldWidget)
17 type_of_talk = schema.Choice(
18 title="Type of talk",
19 values=["talk", "training", "keynote"],
20 required=True,
21 )
22
23 details = RichText(
24 title="Details",
25 description="Description of the talk (max. 2000 characters)",
26 max_length=2000,
27 required=True,
28 )
29
30 directives.widget(audience=CheckBoxFieldWidget)
31 audience = schema.Set(
32 title="Audience",
33 value_type=schema.Choice(
34 values=["beginner", "advanced", "professional"],
35 ),
36 required=False,
37 )
38
39 speaker = schema.TextLine(
40 title="Speaker",
41 description="Name (or names) of the speaker",
42 required=False,
43 )
44
45 company = schema.TextLine(
46 title="Company",
47 required=False,
48 )
49
50 email = Email(
51 title="Email",
52 description="Email address of the speaker",
53 required=False,
54 )
55
56 website = schema.TextLine(
57 title="Website",
58 required=False,
59 )
60
61 github = schema.TextLine(
62 title="Github username",
63 required=False,
64 )
65
66 image = NamedBlobImage(
67 title="Image",
68 description="Portrait of the speaker",
69 required=False,
70 )
71
72 speaker_biography = RichText(
73 title="Speaker Biography (max. 1000 characters)",
74 max_length=1000,
75 required=False,
76 )
77
78
79@implementer(ITalk)
80class Talk(Container):
81 """Talk instance class"""
The first class ITalk is the schema for talks and defines quite a lot of different fields for different kinds of data.
The fields in the schema are mostly from
zope.schema.The most basic field is
schema.TextLinewhich can store text.In the next chapter you will find a reference of all field types available in Plone.
The widget directives can be ignored by now, as we are implementing for a Volto frontend. The widget directives do control the rendering of the fields in Plone Blicca. In the rare case that you need to tweak the rendering of a field in the frontend, this can be done as described in Forms and widgets.
12.4. The instance class#
The second class Talk in talk.py will be the class of instances for each talk.
It inherits from Container which is one of the default classes of dexterity.
Container is used for items that can contain other items.
It does nothing special so far, but it can be useful later when we want to add methods or properties to it that can be used directly from a talk instance.
12.5. Try the new type#
Now all pieces should be in place and you can enable the new type talk.
Restart Plone (to load the new Python code). You do not need to restart the Volto frontend, since we did not do any changes there.
Reinstall the package ploneconf.site to apply the updated profile.
Go to Site Setup.
Open the Add-Ons control panel.
Find
PLONECONF SITE: INSTALLin the list of installed add-ons and click to open its details.Click the Uninstall button.
Find it again and click the Install button.
Now instances of the new type can be added. Please check that you can add a talk to your site.
Adding a talk in the frontend#
Test the type by adding a talk. Add some values in the fields, save it, look at the view, and edit it again.
Compare all the fields you see to the code in the schema.
You can also make changes in the schema. After restarting the backend, these changes are effective immediately.
Find the tool
portal_typesin the ZMI: http://localhost:8080/manage. Look at the FTI for typetalkand inspect the configuration taken from the FTI. You can make changes to the FTI here.A part of the configuration is also available in Site Setup. For example the Content Types control panel allows to add behaviors to content types. Please be aware that these changes are done in your site database, but not on the filesystem. You can use the browser UI, but then the configuration can get out of sync with your filesystem add-on package.
The field values of your talk instance are listed. In one of the next chapters we will create a custom view for the new type.
12.6. Summary#
You created a custom content type.
You can now control the data that will be stored for talks.
You can reuse and adapt these examples to model data for your own use cases.
Next up: After looking at even more fields that are available in Plone, you will learn to change how talks are displayed.
See also
Plone documentation about
Example content type - A Plone content type with all available fields