Content type management#
The @content-types service lists, configures, creates, copies, and deletes content types.
It is available at the site root, and requires the Plone Site Setup: Overview permission, as well as permission to use the REST API.
Use the Types service to edit the schema of a content type.
The dexterity-types control panel of the Control Panels service remains available.
See also
This page used to show example representations of the default content types. They are now in Representations of the default content types.
Method |
Path |
Result |
|---|---|---|
|
|
Every content type with its settings. |
|
|
One content type with its settings. |
|
|
Create a Dexterity content type, optionally copying another one. |
|
|
Change some settings of a content type. |
|
|
Delete a Dexterity content type that has no items. |
Encode content type IDs in URLs, for example News%20Item.
Unknown content types and extra path segments return 404 Not Found.
List content types#
Send a GET request to /@content-types to list every content type with its settings.
http
GET /plone/@content-types HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
curl
curl -i -X GET http://nohost/plone/@content-types -H "Accept: application/json" --user admin:secret
httpie
http http://nohost/plone/@content-types Accept:application/json -a admin:secret
python-requests
requests.get('http://nohost/plone/@content-types', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
The response contains @id, items, and items_total.
Each item has the representation of a single content type, described below.
Get a content type#
Send a GET request to /@content-types/{type} to get one content type.
http
GET /plone/@content-types/Event HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
curl
curl -i -X GET http://nohost/plone/@content-types/Event -H "Accept: application/json" --user admin:secret
httpie
http http://nohost/plone/@content-types/Event Accept:application/json -a admin:secret
python-requests
requests.get('http://nohost/plone/@content-types/Event', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
HTTP/1.1 200 OK
Content-Type: application/json
{
"@id": "http://localhost:55001/plone/@content-types/Event",
"data": {
"allow_discussion": false,
"allowed_content_types": [],
"allowed_content_types_mode": {
"title": "No types",
"token": "none"
},
"behaviors": [
{
"title": "Full-Text Indexing",
"token": "plone.textindexer"
},
{
"title": "Event Basic",
"token": "plone.eventbasic"
},
{
"title": "Event Recurrence",
"token": "plone.eventrecurrence"
},
{
"title": "Event Location",
"token": "plone.eventlocation"
},
{
"title": "Event Attendees",
"token": "plone.eventattendees"
},
{
"title": "Event Contact",
"token": "plone.eventcontact"
},
{
"title": "Dublin Core metadata",
"token": "plone.dublincore"
},
{
"title": "Name from title",
"token": "plone.namefromtitle"
},
{
"title": "RichText",
"token": "plone.richtext"
},
{
"title": "Allow discussion",
"token": "plone.allowdiscussion"
},
{
"title": "Exclude From navigation",
"token": "plone.excludefromnavigation"
},
{
"title": "Short name",
"token": "plone.shortname"
},
{
"title": "Related items",
"token": "plone.relateditems"
},
{
"title": "Versioning",
"token": "plone.versioning"
},
{
"title": "Locking",
"token": "plone.locking"
}
],
"default_page": true,
"description": "Events can be shown in calendars.",
"global_allow": true,
"searchable": true,
"title": "Event",
"versioning": {
"title": "Automatic",
"token": "automatic"
}
},
"id": "Event",
"items_total": 0,
"schema": {
"fieldsets": [
{
"fields": [
"title",
"description"
],
"id": "general",
"title": "General"
},
{
"fields": [
"global_allow",
"allowed_content_types_mode",
"allowed_content_types"
],
"id": "contents",
"title": "Contents"
},
{
"fields": [
"searchable",
"default_page"
],
"id": "visibility",
"title": "Visibility"
},
{
"fields": [
"allow_discussion"
],
"id": "comments",
"title": "Comments"
},
{
"fields": [
"behaviors"
],
"id": "behaviors",
"title": "Behaviors"
},
{
"fields": [
"versioning"
],
"id": "versioning",
"title": "Versioning"
}
],
"properties": {
"allow_discussion": {
"description": "",
"factory": "Yes/No",
"title": "Allow comments",
"type": "boolean"
},
"allowed_content_types": {
"additionalItems": true,
"default": [],
"description": "Kept while all types are allowed",
"factory": "Multiple Choice",
"items": {
"choices": [
[
"TempFolder",
"TempFolder"
],
[
"Plone Site",
"Plone Site"
],
[
"Collection",
"Collection"
],
[
"Document",
"Page"
],
[
"Folder",
"Folder"
],
[
"Link",
"Link"
],
[
"File",
"File"
],
[
"Image",
"Image"
],
[
"News Item",
"News Item"
],
[
"Event",
"Event"
],
[
"Discussion Item",
"Comment"
],
[
"ATTestDocument",
"Test Document"
],
[
"ATTestFolder",
"Test Folder"
],
[
"DXTestDocument",
"DX Test Document"
]
],
"description": "",
"enum": [
"TempFolder",
"Plone Site",
"Collection",
"Document",
"Folder",
"Link",
"File",
"Image",
"News Item",
"Event",
"Discussion Item",
"ATTestDocument",
"ATTestFolder",
"DXTestDocument"
],
"enumNames": [
"TempFolder",
"Plone Site",
"Collection",
"Page",
"Folder",
"Link",
"File",
"Image",
"News Item",
"Event",
"Comment",
"Test Document",
"Test Folder",
"DX Test Document"
],
"factory": "Choice",
"title": "",
"type": "string",
"vocabulary": {
"@id": "http://localhost:55001/plone/portal_types/Event/@sources/"
}
},
"title": "Selected types",
"type": "array",
"uniqueItems": true
},
"allowed_content_types_mode": {
"choices": [
[
"all",
"All types"
],
[
"selected",
"Selected types"
],
[
"none",
"No types"
]
],
"description": "Whether all types, only the selected types, or no types can be added inside content of this type",
"enum": [
"all",
"selected",
"none"
],
"enumNames": [
"All types",
"Selected types",
"No types"
],
"factory": "Choice",
"title": "Allowed content types",
"type": "string",
"vocabulary": {
"@id": "http://localhost:55001/plone/portal_types/Event/@sources/allowed_content_types_mode"
}
},
"behaviors": {
"additionalItems": true,
"default": [],
"description": "The complete list of the type's behaviors. Their order sets where their fields appear in the edit form.",
"factory": "Multiple Choice",
"items": {
"choices": [
[
"plone.allowdiscussion",
"Allow discussion"
],
[
"plone.basic",
"Basic metadata"
],
[
"plone.categorization",
"Categorization"
],
[
"plone.collection",
"Collection"
],
[
"plone.constraintypes",
"Folder Addable Constrains"
],
[
"plone.dublincore",
"Dublin Core metadata"
],
[
"plone.eventattendees",
"Event Attendees"
],
[
"plone.eventbasic",
"Event Basic"
],
[
"plone.eventcontact",
"Event Contact"
],
[
"plone.eventlocation",
"Event Location"
],
[
"plone.eventrecurrence",
"Event Recurrence"
],
[
"plone.excludefromnavigation",
"Exclude From navigation"
],
[
"plone.leadimage",
"Lead Image"
],
[
"plone.locking",
"Locking"
],
[
"plone.namefromfilename",
"Name from file name"
],
[
"plone.namefromtitle",
"Name from title"
],
[
"plone.navigationroot",
"Navigation root"
],
[
"plone.nextpreviousenabled",
"Next previous navigation"
],
[
"plone.nextprevioustoggle",
"Next previous navigation toggle"
],
[
"plone.ownership",
"Ownership"
],
[
"plone.publication",
"Date range"
],
[
"plone.relateditems",
"Related items"
],
[
"plone.richtext",
"RichText"
],
[
"plone.shortname",
"Short name"
],
[
"plone.tableofcontents",
"Table of contents"
],
[
"plone.textindexer",
"Full-Text Indexing"
],
[
"plone.thumb_icon",
"Thumbs and icon handling"
],
[
"plone.translatable",
"Multilingual Support"
],
[
"plone.versioning",
"Versioning"
],
[
"tests.restapi.test_annotations_behavior",
"Test Annotations Behavior"
],
[
"tests.restapi.test_behavior",
"Test Behavior"
],
[
"volto.blocks",
"Blocks"
],
[
"volto.blocks.editable.layout",
"Blocks (Editable Layout)"
]
],
"description": "",
"enum": [
"plone.allowdiscussion",
"plone.basic",
"plone.categorization",
"plone.collection",
"plone.constraintypes",
"plone.dublincore",
"plone.eventattendees",
"plone.eventbasic",
"plone.eventcontact",
"plone.eventlocation",
"plone.eventrecurrence",
"plone.excludefromnavigation",
"plone.leadimage",
"plone.locking",
"plone.namefromfilename",
"plone.namefromtitle",
"plone.navigationroot",
"plone.nextpreviousenabled",
"plone.nextprevioustoggle",
"plone.ownership",
"plone.publication",
"plone.relateditems",
"plone.richtext",
"plone.shortname",
"plone.tableofcontents",
"plone.textindexer",
"plone.thumb_icon",
"plone.translatable",
"plone.versioning",
"tests.restapi.test_annotations_behavior",
"tests.restapi.test_behavior",
"volto.blocks",
"volto.blocks.editable.layout"
],
"enumNames": [
"Allow discussion",
"Basic metadata",
"Categorization",
"Collection",
"Folder Addable Constrains",
"Dublin Core metadata",
"Event Attendees",
"Event Basic",
"Event Contact",
"Event Location",
"Event Recurrence",
"Exclude From navigation",
"Lead Image",
"Locking",
"Name from file name",
"Name from title",
"Navigation root",
"Next previous navigation",
"Next previous navigation toggle",
"Ownership",
"Date range",
"Related items",
"RichText",
"Short name",
"Table of contents",
"Full-Text Indexing",
"Thumbs and icon handling",
"Multilingual Support",
"Versioning",
"Test Annotations Behavior",
"Test Behavior",
"Blocks",
"Blocks (Editable Layout)"
],
"factory": "Choice",
"title": "",
"type": "string",
"vocabulary": {
"@id": "http://localhost:55001/plone/portal_types/Event/@sources/"
}
},
"title": "Behaviors",
"type": "array",
"uniqueItems": true
},
"default_page": {
"description": "Content of this type can be a folder's default page",
"factory": "Yes/No",
"title": "Usable as a default page",
"type": "boolean"
},
"description": {
"default": "",
"description": "",
"factory": "Text",
"title": "Description",
"type": "string",
"widget": "textarea"
},
"global_allow": {
"description": "Allow adding content of this type in any folder",
"factory": "Yes/No",
"title": "Globally addable",
"type": "boolean"
},
"searchable": {
"description": "",
"factory": "Yes/No",
"title": "Shown in search results",
"type": "boolean"
},
"title": {
"description": "",
"factory": "Text line (String)",
"minLength": 1,
"title": "Title",
"type": "string"
},
"versioning": {
"choices": [
[
"off",
"Off"
],
[
"manual",
"Manual"
],
[
"automatic",
"Automatic"
]
],
"description": "Manual versioning saves a version on request, automatic versioning also on every edit",
"enum": [
"off",
"manual",
"automatic"
],
"enumNames": [
"Off",
"Manual",
"Automatic"
],
"factory": "Choice",
"title": "Versioning",
"type": "string",
"vocabulary": {
"@id": "http://localhost:55001/plone/portal_types/Event/@sources/versioning"
}
}
},
"required": [
"title",
"global_allow",
"allowed_content_types_mode",
"searchable",
"default_page",
"allow_discussion",
"versioning"
],
"type": "object"
},
"title": "Event",
"workflow": {
"follows_default": true,
"id": "simple_publication_workflow"
}
}
Property |
Description |
|---|---|
|
URL of the content type in this service. |
|
Content type ID. |
|
Translated title. |
|
Number of items of this type, including those the current user cannot view. |
|
JSON schema of the settings, with |
|
Current values of the settings, keyed by field name. |
|
Read-only summary of the assigned workflow. |
Each fieldset has an id, a title, and the names of its fields.
Fields marked readOnly in the schema cannot be changed.
Choice values have a token and a title, like in control panels and content.
workflow.id is the first workflow of the type's chain, or null when the type has no workflow.
workflow.follows_default is true when the type uses the site's default workflow, and false when a workflow, or no workflow, is assigned to it explicitly.
Core settings#
Fieldset |
Field |
Value |
|---|---|---|
|
|
Title, not empty. |
|
|
Description. |
|
|
Whether items of this type can be added in any folder. |
|
|
Which types can be added inside items of this type: |
|
|
IDs of the selected types. |
|
|
Whether items of this type are shown in search results. |
|
|
Whether items of this type can be a folder's default page. |
|
|
Whether items of this type allow comments. |
|
|
IDs of the type's behaviors, in order. Dexterity types only. |
|
|
|
allowed_content_types_mode and allowed_content_types work together:
allallows every type.allowed_content_typeskeeps the selection, which applies when you change the mode toselectedlater.selectedallows only the types inallowed_content_types, which can't be empty.noneallows no types, andallowed_content_typesmust be empty.
The service checks these rules against the stored values too, so changing only the mode to none fails while types are selected.
manual versioning saves versions on request, and automatic versioning also saves a version on every edit.
Changing the versioning updates the repository policies of the type and its versioning behavior.
Enabling versioning also enables locking, and disabling versioning keeps locking.
Repository policies added by add-ons are kept.
behaviors is the complete, ordered list of the type's behaviors.
Their order sets where their fields appear in the edit form.
Behaviors are listed by their name, such as plone.dublincore, also when the type stores the interface identifier.
A PATCH replaces the list: a behavior left out is disabled.
Behaviors stored on the type that aren't registered, for example those of an uninstalled add-on, aren't listed and are kept.
In a PATCH that changes behaviors and versioning, the versioning setting decides whether the type has the versioning behavior.
http
PATCH /plone/@content-types/Event HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json
{
"behaviors": [
"plone.eventbasic",
"plone.dublincore",
"plone.namefromtitle",
"plone.leadimage"
]
}
curl
curl -i -X PATCH http://nohost/plone/@content-types/Event -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"behaviors": ["plone.eventbasic", "plone.dublincore", "plone.namefromtitle", "plone.leadimage"]}' --user admin:secret
httpie
echo '{
"behaviors": [
"plone.eventbasic",
"plone.dublincore",
"plone.namefromtitle",
"plone.leadimage"
]
}' | http PATCH http://nohost/plone/@content-types/Event Accept:application/json Content-Type:application/json -a admin:secret
python-requests
requests.patch('http://nohost/plone/@content-types/Event', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'behaviors': ['plone.eventbasic', 'plone.dublincore', 'plone.namefromtitle', 'plone.leadimage']}, auth=('admin', 'secret'))
Use the Behaviors service to list the behaviors and the fields they add, and the behaviors parameter of the Types service to preview the edit form with other behaviors.
Change settings#
Send a PATCH request to /@content-types/{type} with the fields to change.
Fields you don't send keep their values.
http
PATCH /plone/@content-types/conference_event HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json
{
"allowed_content_types": [
"Image",
"File"
],
"allowed_content_types_mode": "selected",
"global_allow": false,
"searchable": true,
"versioning": "manual"
}
curl
curl -i -X PATCH http://nohost/plone/@content-types/conference_event -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"allowed_content_types": ["Image", "File"], "allowed_content_types_mode": "selected", "global_allow": false, "searchable": true, "versioning": "manual"}' --user admin:secret
httpie
echo '{
"allowed_content_types": [
"Image",
"File"
],
"allowed_content_types_mode": "selected",
"global_allow": false,
"searchable": true,
"versioning": "manual"
}' | http PATCH http://nohost/plone/@content-types/conference_event Accept:application/json Content-Type:application/json -a admin:secret
python-requests
requests.patch('http://nohost/plone/@content-types/conference_event', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'allowed_content_types': ['Image', 'File'], 'allowed_content_types_mode': 'selected', 'global_allow': False, 'searchable': True, 'versioning': 'manual'}, auth=('admin', 'secret'))
HTTP/1.1 204 No Content
A choice value can be its token, or an object with a token, as returned in data.
The service validates every change before it stores any of them.
Invalid values, unknown fields, and read-only fields return 400 Bad Request with the field names and messages.
Create a content type#
Send a POST request to /@content-types to create a Dexterity container type with an empty schema.
The body requires a title, and accepts an id and a description.
Without an id, the service derives one from the title.
http
POST /plone/@content-types HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json
{
"description": "An event at a conference.",
"title": "Conference event"
}
curl
curl -i -X POST http://nohost/plone/@content-types -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"description": "An event at a conference.", "title": "Conference event"}' --user admin:secret
httpie
echo '{
"description": "An event at a conference.",
"title": "Conference event"
}' | http POST http://nohost/plone/@content-types Accept:application/json Content-Type:application/json -a admin:secret
python-requests
requests.post('http://nohost/plone/@content-types', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'description': 'An event at a conference.', 'title': 'Conference event'}, auth=('admin', 'secret'))
HTTP/1.1 201 Created
Content-Type: application/json
Location: http://localhost:55001/plone/@content-types/conference_event
{
"@id": "http://localhost:55001/plone/@content-types/conference_event",
"data": {
"allow_discussion": false,
"allowed_content_types": [],
"allowed_content_types_mode": {
"title": "No types",
"token": "none"
},
"behaviors": [
{
"title": "Dublin Core metadata",
"token": "plone.dublincore"
},
{
"title": "Name from title",
"token": "plone.namefromtitle"
}
],
"default_page": false,
"description": "An event at a conference.",
"global_allow": true,
"searchable": true,
"title": "Conference event",
"versioning": {
"title": "Off",
"token": "off"
}
},
"id": "conference_event",
"items_total": 0,
"schema": {
"fieldsets": [
{
"fields": [
"title",
"description"
],
"id": "general",
"title": "General"
},
{
"fields": [
"global_allow",
"allowed_content_types_mode",
"allowed_content_types"
],
"id": "contents",
"title": "Contents"
},
{
"fields": [
"searchable",
"default_page"
],
"id": "visibility",
"title": "Visibility"
},
{
"fields": [
"allow_discussion"
],
"id": "comments",
"title": "Comments"
},
{
"fields": [
"behaviors"
],
"id": "behaviors",
"title": "Behaviors"
},
{
"fields": [
"versioning"
],
"id": "versioning",
"title": "Versioning"
}
],
"properties": {
"allow_discussion": {
"description": "",
"factory": "Yes/No",
"title": "Allow comments",
"type": "boolean"
},
"allowed_content_types": {
"additionalItems": true,
"default": [],
"description": "Kept while all types are allowed",
"factory": "Multiple Choice",
"items": {
"choices": [
[
"TempFolder",
"TempFolder"
],
[
"Plone Site",
"Plone Site"
],
[
"Collection",
"Collection"
],
[
"Document",
"Page"
],
[
"Folder",
"Folder"
],
[
"Link",
"Link"
],
[
"File",
"File"
],
[
"Image",
"Image"
],
[
"News Item",
"News Item"
],
[
"Event",
"Event"
],
[
"Discussion Item",
"Comment"
],
[
"ATTestDocument",
"Test Document"
],
[
"ATTestFolder",
"Test Folder"
],
[
"DXTestDocument",
"DX Test Document"
],
[
"conference_event",
"Conference event"
]
],
"description": "",
"enum": [
"TempFolder",
"Plone Site",
"Collection",
"Document",
"Folder",
"Link",
"File",
"Image",
"News Item",
"Event",
"Discussion Item",
"ATTestDocument",
"ATTestFolder",
"DXTestDocument",
"conference_event"
],
"enumNames": [
"TempFolder",
"Plone Site",
"Collection",
"Page",
"Folder",
"Link",
"File",
"Image",
"News Item",
"Event",
"Comment",
"Test Document",
"Test Folder",
"DX Test Document",
"Conference event"
],
"factory": "Choice",
"title": "",
"type": "string",
"vocabulary": {
"@id": "http://localhost:55001/plone/portal_types/conference_event/@sources/"
}
},
"title": "Selected types",
"type": "array",
"uniqueItems": true
},
"allowed_content_types_mode": {
"choices": [
[
"all",
"All types"
],
[
"selected",
"Selected types"
],
[
"none",
"No types"
]
],
"description": "Whether all types, only the selected types, or no types can be added inside content of this type",
"enum": [
"all",
"selected",
"none"
],
"enumNames": [
"All types",
"Selected types",
"No types"
],
"factory": "Choice",
"title": "Allowed content types",
"type": "string",
"vocabulary": {
"@id": "http://localhost:55001/plone/portal_types/conference_event/@sources/allowed_content_types_mode"
}
},
"behaviors": {
"additionalItems": true,
"default": [],
"description": "The complete list of the type's behaviors. Their order sets where their fields appear in the edit form.",
"factory": "Multiple Choice",
"items": {
"choices": [
[
"plone.allowdiscussion",
"Allow discussion"
],
[
"plone.basic",
"Basic metadata"
],
[
"plone.categorization",
"Categorization"
],
[
"plone.collection",
"Collection"
],
[
"plone.constraintypes",
"Folder Addable Constrains"
],
[
"plone.dublincore",
"Dublin Core metadata"
],
[
"plone.eventattendees",
"Event Attendees"
],
[
"plone.eventbasic",
"Event Basic"
],
[
"plone.eventcontact",
"Event Contact"
],
[
"plone.eventlocation",
"Event Location"
],
[
"plone.eventrecurrence",
"Event Recurrence"
],
[
"plone.excludefromnavigation",
"Exclude From navigation"
],
[
"plone.leadimage",
"Lead Image"
],
[
"plone.locking",
"Locking"
],
[
"plone.namefromfilename",
"Name from file name"
],
[
"plone.namefromtitle",
"Name from title"
],
[
"plone.navigationroot",
"Navigation root"
],
[
"plone.nextpreviousenabled",
"Next previous navigation"
],
[
"plone.nextprevioustoggle",
"Next previous navigation toggle"
],
[
"plone.ownership",
"Ownership"
],
[
"plone.publication",
"Date range"
],
[
"plone.relateditems",
"Related items"
],
[
"plone.richtext",
"RichText"
],
[
"plone.shortname",
"Short name"
],
[
"plone.tableofcontents",
"Table of contents"
],
[
"plone.textindexer",
"Full-Text Indexing"
],
[
"plone.thumb_icon",
"Thumbs and icon handling"
],
[
"plone.translatable",
"Multilingual Support"
],
[
"plone.versioning",
"Versioning"
],
[
"tests.restapi.test_annotations_behavior",
"Test Annotations Behavior"
],
[
"tests.restapi.test_behavior",
"Test Behavior"
],
[
"volto.blocks",
"Blocks"
],
[
"volto.blocks.editable.layout",
"Blocks (Editable Layout)"
]
],
"description": "",
"enum": [
"plone.allowdiscussion",
"plone.basic",
"plone.categorization",
"plone.collection",
"plone.constraintypes",
"plone.dublincore",
"plone.eventattendees",
"plone.eventbasic",
"plone.eventcontact",
"plone.eventlocation",
"plone.eventrecurrence",
"plone.excludefromnavigation",
"plone.leadimage",
"plone.locking",
"plone.namefromfilename",
"plone.namefromtitle",
"plone.navigationroot",
"plone.nextpreviousenabled",
"plone.nextprevioustoggle",
"plone.ownership",
"plone.publication",
"plone.relateditems",
"plone.richtext",
"plone.shortname",
"plone.tableofcontents",
"plone.textindexer",
"plone.thumb_icon",
"plone.translatable",
"plone.versioning",
"tests.restapi.test_annotations_behavior",
"tests.restapi.test_behavior",
"volto.blocks",
"volto.blocks.editable.layout"
],
"enumNames": [
"Allow discussion",
"Basic metadata",
"Categorization",
"Collection",
"Folder Addable Constrains",
"Dublin Core metadata",
"Event Attendees",
"Event Basic",
"Event Contact",
"Event Location",
"Event Recurrence",
"Exclude From navigation",
"Lead Image",
"Locking",
"Name from file name",
"Name from title",
"Navigation root",
"Next previous navigation",
"Next previous navigation toggle",
"Ownership",
"Date range",
"Related items",
"RichText",
"Short name",
"Table of contents",
"Full-Text Indexing",
"Thumbs and icon handling",
"Multilingual Support",
"Versioning",
"Test Annotations Behavior",
"Test Behavior",
"Blocks",
"Blocks (Editable Layout)"
],
"factory": "Choice",
"title": "",
"type": "string",
"vocabulary": {
"@id": "http://localhost:55001/plone/portal_types/conference_event/@sources/"
}
},
"title": "Behaviors",
"type": "array",
"uniqueItems": true
},
"default_page": {
"description": "Content of this type can be a folder's default page",
"factory": "Yes/No",
"title": "Usable as a default page",
"type": "boolean"
},
"description": {
"default": "",
"description": "",
"factory": "Text",
"title": "Description",
"type": "string",
"widget": "textarea"
},
"global_allow": {
"description": "Allow adding content of this type in any folder",
"factory": "Yes/No",
"title": "Globally addable",
"type": "boolean"
},
"searchable": {
"description": "",
"factory": "Yes/No",
"title": "Shown in search results",
"type": "boolean"
},
"title": {
"description": "",
"factory": "Text line (String)",
"minLength": 1,
"title": "Title",
"type": "string"
},
"versioning": {
"choices": [
[
"off",
"Off"
],
[
"manual",
"Manual"
],
[
"automatic",
"Automatic"
]
],
"description": "Manual versioning saves a version on request, automatic versioning also on every edit",
"enum": [
"off",
"manual",
"automatic"
],
"enumNames": [
"Off",
"Manual",
"Automatic"
],
"factory": "Choice",
"title": "Versioning",
"type": "string",
"vocabulary": {
"@id": "http://localhost:55001/plone/portal_types/conference_event/@sources/versioning"
}
}
},
"required": [
"title",
"global_allow",
"allowed_content_types_mode",
"searchable",
"default_page",
"allow_discussion",
"versioning"
],
"type": "object"
},
"title": "Conference event",
"workflow": {
"follows_default": true,
"id": "simple_publication_workflow"
}
}
The new type has the same defaults as one created in the classic "Dexterity Content Types" control panel.
The service returns 409 Conflict when a type with the ID exists.
Copy a content type#
Add copy_from with the ID of a Dexterity content type to copy it.
The copy has the schema, behaviors, settings, actions, repository policies, and workflow assignment of the source.
Without a description, it also has the source's description.
http
POST /plone/@content-types HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json
{
"copy_from": "Event",
"description": "An event at a conference.",
"id": "ConferenceEvent",
"title": "Conference event"
}
curl
curl -i -X POST http://nohost/plone/@content-types -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"copy_from": "Event", "description": "An event at a conference.", "id": "ConferenceEvent", "title": "Conference event"}' --user admin:secret
httpie
echo '{
"copy_from": "Event",
"description": "An event at a conference.",
"id": "ConferenceEvent",
"title": "Conference event"
}' | http POST http://nohost/plone/@content-types Accept:application/json Content-Type:application/json -a admin:secret
python-requests
requests.post('http://nohost/plone/@content-types', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'copy_from': 'Event', 'description': 'An event at a conference.', 'id': 'ConferenceEvent', 'title': 'Conference event'}, auth=('admin', 'secret'))
Changes to the copy, including to its schema, don't affect the source.
Delete a content type#
Send a DELETE request to /@content-types/{type} to delete a Dexterity content type.
http
DELETE /plone/@content-types/conference_event HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
curl
curl -i -X DELETE http://nohost/plone/@content-types/conference_event -H "Accept: application/json" --user admin:secret
httpie
http DELETE http://nohost/plone/@content-types/conference_event Accept:application/json -a admin:secret
python-requests
requests.delete('http://nohost/plone/@content-types/conference_event', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
HTTP/1.1 204 No Content
Deleting a type also removes its settings, its workflow assignment, and its use as an allowed type of other types. A type created later with the same ID starts with default settings.
While items of the type exist, the service returns 409 Conflict with their number.
HTTP/1.1 409 Conflict
Content-Type: application/json
{
"error": {
"message": "The content type still has items",
"type": "Conflict"
},
"items_total": 1
}
Add settings from an add-on#
Each fieldset comes from a named adapter providing plone.restapi.typesettings.interfaces.ITypeSettings.
The core fieldsets use the same mechanism, so an add-on can add its own settings to every content type.
Because the response includes a JSON schema, a frontend can show them without knowing the add-on.
An adapter adapts the FTI and the request, and has these attributes and methods:
Name |
Description |
|---|---|
|
Fieldset title. |
|
Sort order of the fieldset, lowest first. The core fieldsets use 10 to 50. |
|
|
|
Permission ID needed to see and change the fieldset, or |
|
Return the current values. |
|
Return a list of errors for the changed values, each with |
|
Store the changed values. |
|
Delete what the settings store outside the FTI, before the type is deleted. |
The service converts values with the registered field serializers and deserializers, and validates them with the field constraints and the schema invariants.
It applies plone.autoform directives such as omitted, mode, and order_before.
Use flat fields: values of schema.Object fields aren't converted to and from JSON.
Subclass plone.restapi.typesettings.settings.TypeSettings to store settings as FTI properties, or override its methods to store them elsewhere.
This example stores a setting in the registry:
from plone.registry.interfaces import IRegistry
from plone.restapi.typesettings.settings import TypeSettings
from zope import schema
from zope.component import getUtility
from zope.interface import Interface
class ISponsorSettings(Interface):
sponsors_enabled = schema.Bool(title="Show sponsors")
class SponsorSettings(TypeSettings):
title = "Sponsors"
order = 100
schema = ISponsorSettings
record = "collective.sponsors.types"
def read(self):
types = getUtility(IRegistry)[self.record]
return {"sponsors_enabled": self.context.getId() in types}
def write(self, data):
registry = getUtility(IRegistry)
types = set(registry[self.record]) - {self.context.getId()}
if data["sponsors_enabled"]:
types.add(self.context.getId())
registry[self.record] = sorted(types)
def remove(self):
self.write({"sponsors_enabled": False})
<adapter
factory=".settings.SponsorSettings"
name="collective.sponsors"
/>