--- myst: html_meta: "description": "" "property=og:description": "" "property=og:title": "" "keywords": "" --- (plone5-export-code-label)= # Return to Dexterity: Moving contenttypes into Code ````{sidebar} Get the code! Code for the beginning of this chapter: ```shell git checkout eggs1 ``` Code for the end of this chapter: ```shell git checkout export_code ``` {doc}`code` ```` In this part you will: - Move the _Talk_ type into {py:mod}`ploneconf.site` - Improve the schema and the FTI Topics covered: - Content type definitions with generic setup - FTI - XML schema - more widgets Remember the _Talk_ content type that we created through-the-web with Dexterity? Let's move that new content type into our add-on package so that it may be installed in other sites without TTW manipulation. Steps: - Return to the Dexterity control panel - Export the _Talk_ Type Profile and save the file - Delete the _Talk_ from the site before installing it from the file system - Extract the files from the exported tar file and add them to our add-on package in {file}`profiles/default/` ```{note} From the buildout directory perspective that is {file}`src/ploneconf.site/src/ploneconf/site/profiles/default/` ``` The file {file}`profiles/default/types.xml` tells Plone that there is a new content type defined in file {file}`talk.xml`. ```xml Controls the available contenttypes in your portal ``` Upon installing, Plone reads the file {file}`profiles/default/types/talk.xml` and registers a new type in `portal_types` (you can find and inspect this tool in the ZMI!) with the information taken from that file. ```xml Talk None string:${portal_url}/document_icon.png talk string:${folder_url}/++add++talk view True True False view False cmf.AddPortalContent plone.dexterity.content.Container <?xml version='1.0' encoding='utf8'?> <model xmlns:lingua="http://namespaces.plone.org/supermodel/lingua" xmlns:users="http://namespaces.plone.org/supermodel/users" xmlns:form="http://namespaces.plone.org/supermodel/form" xmlns:i18n="http://xml.zope.org/namespaces/i18n" xmlns:security="http://namespaces.plone.org/supermodel/security" xmlns:marshal="http://namespaces.plone.org/supermodel/marshal" xmlns="http://namespaces.plone.org/supermodel/schema"> <schema> <field name="type_of_talk" type="zope.schema.Choice"> <description/> <title>Type of talk</title> <values> <element>Talk</element> <element>Training</element> <element>Keynote</element> </values> </field> <field name="details" type="plone.app.textfield.RichText"> <description>Add a short description of the talk (max. 2000 characters)</description> <max_length>2000</max_length> <title>Details</title> </field> <field name="audience" type="zope.schema.Set"> <description/> <title>Audience</title> <value_type type="zope.schema.Choice"> <values> <element>Beginner</element> <element>Advanced</element> <element>Professionals</element> </values> </value_type> </field> <field name="speaker" type="zope.schema.TextLine"> <description>Name (or names) of the speaker</description> <title>Speaker</title> </field> <field name="email" type="plone.schema.email.Email"> <description>Adress of the speaker</description> <title>Email</title> </field> <field name="image" type="plone.namedfile.field.NamedBlobImage"> <description/> <required>False</required> <title>Image</title> </field> <field name="speaker_biography" type="plone.app.textfield.RichText"> <description/> <max_length>1000</max_length> <required>False</required> <title>Speaker Biography</title> </field> </schema> </model> dexterity ``` Now our package has new configuration for Generic Setup. Generic Setup store the configiuration for the site in the folder {file}`profiles/`. This configuration is applied to your site upon installing the package. So, we'll need to reinstall it (if installed before). - Restart Plone. - Re-install ploneconf.site (deactivate and activate). - Test the type by adding an object or editing one of the old ones. - Look at how the talks are presented in the browser. The escaped inline xml is simply too ugly to look at. You should move it to a separate file! Create a new folder {file}`content` in the main directory (from the buildout directory perspective that is {file}`src/ploneconf.site/src/ploneconf/site/content/`). Inside add an empty file {file}`__init__.py` and a file {file}`talk.xml` that contains the real XML (copied from and beautified with some online XML formatter ()) ```{code-block} xml :linenos: Type of Talk Talk Training Keynote Add a short description of the talk (max. 2000 characters)/> 2000 Details Audience Beginner Advanced Professional Name (or names) of the speaker/> Speaker Adress of the speaker/> Email False Image 1000 False Speaker Biography ``` Now remove the ugly model_source and instead point to the new XML file in the FTI by using the property `model_file`: ```xml ploneconf.site.content:talk.xml ``` `ploneconf.site.content:talk.xml` points to a file {file}`talk.xml` to be found in the Python path `ploneconf.site.content`. The {file}`__init__.py` is needed to turn the folder {file}`content` into a Python package. It is best-practice to add schemas in this folder, and in later chapters you will add new types with pythons-schemata in the same folder. ```{note} The default types of Plone 5 also have an xml schema like this since that allows the fields of the types to be editable trough the web! Fields for types with a python schema are not editable ttw. ``` ## Changing a widget [Dexterity XML](https://5.docs.plone.org/external/plone.app.dexterity/docs/reference/dexterity-xml.html) is very powerful. By editing it (not all features have a UI) you should be able to do everything you can do with a Python schema. Sadly not every feature also is exposed in the UI of the dexterity schema editor. For example you cannot yet change the widgets or permissions for fields in the UI. We need to do this in the xml- or python-schema. Our talks use a dropdown for {guilabel}`type_of_talk` and a multiselect for {guilabel}`audience`. Radio-buttons and checkboxes would be the better choice here. Modify the XML to make that change happen: ```{code-block} xml :emphasize-lines: 11, 26 :linenos: Type of talk Talk Training Keynote Add a short description of the talk (max. 2000 characters) 2000 Details Audience Beginner Advanced Professionals Name (or names) of the speaker Speaker Adress of the speaker Email False Image 1000 False Speaker Biography ``` ## Protect fields with permissions We also want to have a add a new field `room` to show where a talk will take place. Our case-study says the speakers will submit the talks online. How should they know in which room the talk will take place (if it got accepted at all)? So we need to hide this field from them by requiring a permission that they do not have. Let's assume the prospective speakers will not have the permission to review content (i.e. edit submitted content and publish it) but the organizing commitee has. You can then protect the field using the permission `Review portal content` in this case the name of the permission-utility for this permission: `cmf.ReviewPortalContent`. We only want to prevent writing, not reading, so we'll only manage the `write-permission`: ```{code-block} xml :emphasize-lines: 38-50 :linenos: Type of talk Talk Training Keynote Add a short description of the talk (max. 2000 characters) 2000 Details Audience Beginner Advanced Professionals False Room 101 201 Auditorium Name (or names) of the speaker Speaker Adress of the speaker Email False Image 1000 False Speaker Biography ``` ```{seealso} - - ``` ### Exercise 1 Go to the ZMI and look for the definition of the new `Talk` content type in `portal_types`. Now deactivate {guilabel}`Implicitly addable?` and save. Go back to the site. Can you identify what this change has caused? And why is that useful? ````{dropdown} Solution :animate: fade-in-slide-down :icon: question Go to When disabling *Implicitly addable* you can no longer add Talks any more unless you change some container like the type *Folder*: Enable *Filter contenttypes?* for it and add *Talk* to the items that are allowed. With this method you can prevent content that only makes sense inside some defined structure to show up in places where they do not belong. The equivalent setting for disabling {guilabel}`Implicitly addable` in {file}`Talk.xml` is: ```xml False ``` ```` ## Summary - You can now create new content-types and store them in a reproduceable way - You installed the package to apply the Generic Setup configuration - You learned how to read and modify the content type schema in xml