Templates and Components to Page
Plone Theme Reference
1. Templates and Components to Page
An overview of how templates, viewlets, and portlets mesh together to create a page.
Plone's page templates can be frustrating at first. There's no single template which seems to contain everything you need.
Content Views
Since each content type is likely to have a different combination of fields, each content type requires a separate template for display. As we saw in the templates and templating language section, these usually have _view appended to their name. You can find those for the standard Plone content types in
- [your zope instance]/Products/CMFPlone/Skins/plone_content.
main_template
Knowing about content views only gets you so far, however. It is the main template (main_template.pt) which draws the content together with the page furniture and design. You can find this in
- [your zope instance]/Products/CMFPlone/skins/plone_templates.
It is important to remember that the content view templates aren't complete in themselves, they merely provide a snippet of content which is dropped into a "slot" in the main_template - called 'main'.

If you feel unsure about slots, then have a look back at the templates and templating language section.
Around this main slot, the components - viewlets and portlets come into play - supplying the page furniture and decoration around the content. The main template simply pulls these in via viewlet managers and portlet managers.
Viewlets are so flexible that they can even be pulled into the content view. The abovecontentbody manager, for instance, is used in a number of content views, and handles, amongst other things, the presentation viewlet we looked at in previous sections.
In more detail
You might find it helpful to look at an example in context.
Have a look at:
- Products/CMFPlone/Skins/plone_templates/main_template
and
- Products/CMFPlone/Skins/plone_content/document_view
About document_view (a content view template)
1. Although document_view looks like a complete HTML page, ignore this. Just note that right at the top it calls the main_template.
metal:use-macro="here/main_template/macros/master"
The code that gets used from document_view is actually the bit between these tags:
<metal:main fill-slot="main"> â¦â¦ </metal:main>
This gets dropped into a slot in the main_template:
<metal:bodytext metal:define-slot="main"
tal:content="nothing">
...
</metal:bodytext>
2. Going back to the fill-slot in the document_view youâll see a few tags calling the relevant fields from the content type â like this:
<metal:field
use-macro="python:here.widget('title', mode='view')">
</metal:field>
Youâll also see a few tags like calling viewlet managers which, in turn, will summon up groups of viewlets:
<div tal:replace="structure provider:plone.abovecontentbody" />
These enable you to drop extra bits of page furniture around the specific content from the fields (e.g., the presentation mode link).
About the main template
1. Jump back to main_template and youâll see similar calls to other viewlet managers managing groups of viewlets for more page furniture:
<div tal:replace="structure provider:plone.portaltop" />
2. And calls to portlet managers to pull up the portlets defined for that particular page:
<tal:block replace="structure provider:plone.leftcolumn" />
3. Youâll also see a number of additional slots (define-slot), which could also be filled (fill-slot) from the content view template if you wanted. Here's one you could use to add a bit of css:
<metal:styleslot define-slot="style_slot" />
Jump back to your content view template and simply add an additional fill-slot (outside of the main fill-slot):
<metal:mystyleslot fill-slot="style_slot"> ..... </metal:mystyleslot>
We'll go into other ways of providing styles in more detail in the next section.
2. How to show full content in folder views
This how-to only makes sense for folders, smart folder, or other similar views with a reasonably small number of items. It shows how to display the full view of content in listings by using the macros already defined for the content types. The same approach can be used to define viewlets for layout products like compositepack.
I was looking for a layout product for the front page of a site I am working on, and the existing products did not meet my needs out of the box because they only showed summary views of content rather than the full view. Instead of writing viewlets for different content types from scratch, I used the existing view macros of the content types as follows, in a new folder view I called folder_full_view (this is just a code snippet):
<tal:listing condition="folderContents"> <div tal:repeat="item folderContents"> <tal:block tal:define="here item/getObject; actions nothing; view here/defaultView; object_title item/pretty_title_or_id" tal:on-error="nothing"> <div metal:use-macro="here/?view/macros/main"/> </tal:block> </div> </tal:listing>
The setting of actions to nothing is so that the action icons are not displayed for every content item. The on-error="nothing" may not be necessary for you. I have it because I allow the catalog to return results for which there is no View permission.
Similarly, for the CompositePack product, I defined a viewlet
<div class="viewlet default_view"> <tal:block on-error="nothing" tal:define="here nocall: context; actions nothing; view here/defaultView; object_title here/pretty_title_or_id"> <metal:block use-macro="context/global_defines/macros/defines" /> <div metal:use-macro="context/?view/macros/main"/> </tal:block> </div>
so that complete content can be displayed in a layout.
Use these ideas at your own risk. Seems to work for me so far.
3. How to scale images using PiL in Page Templates
A quick description of how to scale images from an image field using the Python Image Library in your Page Templates using TAL.
PROBLEM:
I have a custom type with an ImageField. I'm customizing a folder listing of these types and I wanted a thumbnail of each image shown in the folder listing. This is very straightforward using PiL (Python Imaging Library), if you know what to do. I was also presented with the problem of working with brains rather than the object itself.
ASSUMPTIONS:
- You have PiL installed and working.
- You know how to make a custom Archetype
OVERVIEW:
When you get the folder contents for a folder listing, brains objects are returned and iterated over to produce the list. This is of course, much more efficient than waking up each object. The problem being, you cannot get to your Image field in a brain (that I know of). The following is a snippet from 'folder_listing.pt' showing this.
<tal:foldercontents define="contentFilter contentFilter|request/contentFilter|nothing;
contentsMethod python:test(here.portal_type=='Topic', here.queryCatalog, here.getFolderContents);
folderContents folderContents|python:contentsMethod(contentFilter);">
<tal:entry tal:repeat="item folderContents">
<tal:block tal:define="item_url item/getURL|item/absolute_url;">
As you can see, while iterating over 'item' you're accessing brains-y things in a brains-y way, like 'item/getURL'. But you'll notice that you cannot do 'item/my_image' because it's not in the brain. What to do?! you may wail. Well, you could wake up the objects, get the image field, and then call the image scaling on it in a pythonic way, but this is a performance hit, puts python in your TAL, whcih you should avoid.
Instead you'll just be crafty. You already have 'item_url' and you know the name of your image field (my-image) so put those together and you'll get right at the image. Try this in your browser:
http://full/url/to/your/object/my-image
and you should see your image! Translating this into TAL, you would go:
<img src="#" tal:attributes="src string:${item_url}/my-image" />
Now to add the image scaling bit, and this is where I went wrong. Much of the Plone documentation about PiL assume you're working with an ATImage object, but you're not. You're working with an AT ImageField. An AT ImageField only defines ONE image scale size by default:
sizes = {'thumb': (80,80)}
whereas ATImage defines a bunch:
sizes = {'large' : (768, 768),
'preview' : (400, 400),
'mini' : (200, 200),
'thumb' : (128, 128),
'tile' : (64, 64),
'icon' : (32, 32),
'listing' : (16, 16),
},
To make matters worse, notice that the sizes defined for the same size key are different. Bad dog. No cookie. Anyhow, what this means is that in order to access the size you want, you have to define it in your schema in advance, like so:
ImageField(
name='my-image',
widget=ImageWidget(
label="My Image",
description="An image!",
),
storage=AttributeStorage(),
sizes= {'large' : (768, 768),
'preview' : (400, 400),
'mini' : (200, 200),
'thumb' : (128, 128),
'tile' : (64, 64),
'icon' : (32, 32),
'listing' : (16, 16),
},
),
Ok, so now that you have defined the sizes you want in your custom type's schema, you're ready to use it in your Page Template. Remember the way we accessed it before?
<img src="#" tal:attributes="src string:${item_url}/my-image" />
To access the sizes defined in your schema, just add the name to the end of your image, preceded by an underscore.
<img src="#" tal:attributes="src string:${item_url}/my-image_mini" />
It's that easy, and it should be. You shouldn't have to access and therefore wake up your objects! There are also other ways to get at PiL's image scaling, but this I found was easiest and didn't throw any bizarro "Unauthorized" or "TypeError: a float is required" errors.
Enjoy!
~Spanky
ALSO SEE:
http://plone.org/documentation/manual/archetypes-developer-manual/fields/fields-referencehttp://plone.org/documentation/tutorial/richdocument/pil
Author: