--- myst: html_meta: "description": "" "property=og:description": "" "property=og:title": "" "keywords": "" --- (dexterity-3-label)= # Dexterity Types III: Sponsors ````{sidebar} Plone Backend Chapter ```{figure} _static/plone-training-logo-for-backend.svg :alt: Plone backend :class: logo ``` Get the code! ({doc}`More info `) Code for the beginning of this chapter: ```shell git checkout resources ``` Code for the end of this chapter: ```shell git checkout dexterity_3 ``` ```` Without sponsors, a conference would be hard to finance! Plus it is a good opportunity for Plone companies to advertise their services. In this part we will: - Create a sponsor contenttype to manage sponsors - Store non-visible information about the sponsor in the sponsor-type The topics we cover are: - Schema hint and directives - Field permissions - Vocabularies ## The Python schema First we create the schema for the new content type. Add a new file {file}`content/sponsor.py`. ```{code-block} python :linenos: from plone.app.textfield import RichText from plone.autoform import directives from plone.dexterity.content import Container from plone.namedfile import field as namedfile from plone.supermodel import model from plone.supermodel.directives import fieldset from z3c.form.browser.radio import RadioFieldWidget from zope import schema from zope.schema.vocabulary import SimpleTerm from zope.schema.vocabulary import SimpleVocabulary LevelVocabulary = SimpleVocabulary( [SimpleTerm(value='platinum', title='Platinum Sponsor'), SimpleTerm(value='gold', title='Gold Sponsor'), SimpleTerm(value='silver', title='Silver Sponsor'), SimpleTerm(value='bronze', title='Bronze Sponsor')] ) class ISponsor(model.Schema): """Dexterity Schema for Sponsors """ directives.widget(level=RadioFieldWidget) level = schema.Choice( title='Sponsoring Level', vocabulary=LevelVocabulary, required=True ) text = RichText( title='Text', required=False ) url = schema.URI( title='Link', required=False ) fieldset('Images', fields=['logo', 'advertisement']) logo = namedfile.NamedBlobImage( title='Logo', required=False, ) advertisement = namedfile.NamedBlobImage( title='Advertisement (Gold-sponsors and above)', required=False, ) directives.read_permission(notes='cmf.ManagePortal') directives.write_permission(notes='cmf.ManagePortal') notes = RichText( title='Secret Notes (only for site-admins)', required=False ) @implementer(ISponsor) class Sponsor(Container): """Sponsor instance class""" ``` Some things are notable here: - {py:class}`LevelVocabulary` is used to create the options used in the field `level`. This way we could easily translate the displayed value. - {samp}`fieldset('Images', fields=['logo', 'advertisement'])` moves the two image fields to another tab. - {samp}`directives.read_permission(...)` sets the read and write permission for the field `notes` to users who can add new members. Usually this permission is only granted to Site Administrators and Managers. We use it to store information that should not be publicly visible. Please note that {py:attr}`obj.notes` is still accessible in templates and Python. ```{seealso} See the chapter {ref}`dexterity-reference-label` for a reference of all field-types and directives you can use in dexterity. ``` ## The Factory Type Information, or FTI Next, we create the factory type information ("FTI") for the new type in {file}`profiles/default/types/sponsor.xml` ```{code-block} xml :emphasize-lines: 26 :linenos: Sponsor string:${portal_url}/document_icon.png sponsor string:${folder_url}/++add++sponsor view True True False view False cmf.AddPortalContent ploneconf.site.content.sponsor.ISponsor ploneconf.site.content.sponsor.Sponsor dexterity ``` Then we register the FTI in {file}`profiles/default/types.xml` ```{code-block} xml :emphasize-lines: 4 :linenos: ``` After reinstalling our package we can create the new type. ### Exercise 1 Sponsors are containers but they don't need to be. Turn them into items by changing their class to {py:class}`plone.dexterity.content.Item`. ````{dropdown} Solution :animate: fade-in-slide-down :icon: question Modify the instance class. ```{code-block} xml :emphasize-lines: 4 :linenos: from plone.dexterity.content import Item @implementer(ISponsor) class Sponsor(Item): """Sponsor instance class""" ``` ```{note} Changing the base-class of existing content from Item to Container or the other way around is possible but requires. See for details. ``` ```` ## Summary - You created a new content type to store information on sponsors - You learned how to protect individual fields from being edited with permissions - Next you will learn how to display the sponsors at the bottom of every page