Skip to content
Browse files

small wording & grammar updates

  • Loading branch information...
1 parent f2a78b2 commit 7ff6dae81fb1edd1620964daa75c15a9f656ee27 @muellert muellert committed Feb 10, 2012
Showing with 180 additions and 139 deletions.
  1. +180 −139 source/views/browserviews.txt
View
319 source/views/browserviews.txt
@@ -14,42 +14,50 @@ Introduction
Plone/Zope uses a view pattern to output dynamically generated HTML pages.
Views are the basic elements of modern Python web frameworks. A view runs code
-to set-up Python variables for a template rendering. Output may not limited
-to HTML pages and snippets, but may contain JSON, file download payloads and other.
+to set-up Python variables for a template rendering. Output is not limited
+to HTML pages and snippets, but may contain JSON, file download
+payloads, or other data formats.
-Views are usually combination of
+Views are usually a combination of a
-* Python class which performs the user interface logic settup
+* Python class, which performs the user interface logic setup, and a
-* Corresponding page template (in TAL language) or direct Python string output
+* corresponding page template (in TAL language), or direct Python string output
-By keeping as much of the logic code
-in a separate Python class and making page template as dumb as possible
-better component readability and reuse is achieved. You can override
-either Python logic or the template file separately.
+By keeping as much of the view logic in a separate Python class as we
+can and making the page template as dumb as possible, better component
+readability and reuse is achieved. You can override the Python logic
+or the template file, or both.
When you are working with Plone, the most usual view type is *BrowserView* from
Products.Five package, but there are others.
-Each BrowserView class is a Python callable. BrowserView.__call__()
-method acts as an entry point of executing the view code. From Zope point of view,
-even a function would be enough as it is callable.
+Each BrowserView class is a Python callable. The
+BrowserView.__call__() method acts as an entry point to executing the
+view code. From Zope's point of view, even a function would be
+sufficient, as it is a callable.
+
Plain Zope 3 vs. Grok
=====================
-Views were introduced in Zope 3 and made available in Plone by Products.Five package
-(which provides some Plone/Zope 2 specific adaption hooks).
-However, Zope 3's way of XML based configuration languae ZCML and separating things to three different files
-(Python module, ZCML configuration, TAL template) was later seen as cumbersome to maintain.
+Views were introduced in Zope 3 and made available in Plone by way of
+the Products.Five package, which provides some Plone/Zope 2 specific
+adaption hooks to the modern Zope 3 code base. However, Zope 3's way
+of XML based configuration language ZCML and separating things to three
+different files (Python module, ZCML configuration, TAL template) was
+later seen as too cumbersome to maintain.
-Later a project called `Grok <http://grok.zope.org/>`_ was started to introduce easy API to Zope,
-including how to set up and maintain views. For more information how to use Grok (five.grok package)
-with Plone, please read `Plone and Grok tutorial <http://plone.org/products/dexterity/documentation/manual/five.grok>`_.
+Later, a project called `Grok <http://grok.zope.org/>`_ was started to
+introduce an easy API to Zope 3, including a way of how to set up and
+maintain views. For more information about how to use Grok (found in
+the five.grok package) with Plone, please read the `Plone and Grok
+tutorial
+<http://plone.org/products/dexterity/documentation/manual/five.grok>`_.
.. note::
- When writing this (Q1/2010), all project templates in Paster still use old-style Zope views.
+ At the time of writing (Q1/2010), all project templates in Paster still use old-style Zope views.
More information
================
@@ -62,35 +70,38 @@ View components
===============
Views are Zope component architecture multi-adapter registrations.
-If you are doing manual view look-ups then this information concerns you.
+If you are doing manual view look-ups, then this information is
+relevant to you.
-Views are looked up by name. Zope publisher does forced
-view look-up, instead of traversing, if the traversing name is prefixed with @@.
+Views are looked up by name. The Zope publisher does a forced view
+look-up, instead of traversing, if the traversing name is prefixed
+with @@.
Views are resolved against different interfaces
-* context: Any class/interface. If not given zope.interface.Interface is used (corresponds for="*")
+* context: Any class/interface. If not given, zope.interface.Interface is used (corresponds for="*")
-* request: Always HTTP request. Interface zope.publisher.interfaces.browser.IBrowserRequest is used.
+* request: The current HTTP request. Interface zope.publisher.interfaces.browser.IBrowserRequest is used.
-* layer: Theme layer interface. If not given zope.publisher.interfaces.browser.IDefaultBrowserLayer is used.
+* layer: Theme layer interface. If not given, zope.publisher.interfaces.browser.IDefaultBrowserLayer is used.
See also `related source code <http://svn.zope.org/zope.browserpage/trunk/src/zope/browserpage/metaconfigure.py?rev=103273&view=auto>`_.
Finding a view to override
--------------------------
-Here is short introduction how to find how existing views are defined.
-First, you go to portal_types to look what views have been registered to a particular content.
+Here is a short introduction on finding how existing views are
+defined. First, you go to portal_types to see what views have been
+registered to a particular content type.
For example, if you want to override *Folder's* Tabular view, you find out that
-it is registered as ``/folder_tabular_view`` handler.
+it is registered as the handler for ``/folder_tabular_view``.
-You look for *folder_tabular_view* old style page
-template or ``@@folder_tabular_view`` BrowserView ZCML registration in Plone source tree -
-it can be either.
+You look for *folder_tabular_view* old style page templates or
+``@@folder_tabular_view`` BrowserView ZCML registrations in the Plone
+source tree - it can be either.
-Example how to search for this using UNIX tools
+Example how to search for this using UNIX tools:
.. code-block:: console
@@ -100,8 +111,8 @@ Example how to search for this using UNIX tools
grep -Ri --include="*.zcml" folder_tabular_view * # find new style view registrations in ZCML files
-``folder_tabular_view`` is found on :doc:`skin layer </templates_css_and_javascripts/skin_layers>`
-called ``plone_content`` in CMFPlone product.
+The ``folder_tabular_view`` is found in :doc:`skin layer </templates_css_and_javascripts/skin_layers>`
+called ``plone_content`` in the CMFPlone product.
More info
@@ -110,16 +121,16 @@ More info
Creating and registering a view
-------------------------------
-This shows how to create and register view in Zope 3 manner.
+This shows how to create and register view in a Zope 3 manner.
Creating a view using Grok
==============================
This is the simplest method and recommended for Plone 4.1+ onwards.
-First create your add-on product using :doc:`Dexterity project template </tutorials/paste>`.
+First, create your add-on product using :doc:`Dexterity project template </tutorials/paste>`.
-Add file *yourcompany.app/yourcompany/app/browser/views.py*::
+Add the file *yourcompany.app/yourcompany/app/browser/views.py*::
"""
@@ -143,16 +154,16 @@ Add file *yourcompany.app/yourcompany/app/browser/views.py*::
grok.context(Interface)
-The view in the question is not registered against any :doc:`layer </views/layers>`,
-so it is available always. The view becomes available on Zope start-up and is
-available even if you don't run a add-on installer. This is the suggested
+The view in question is not registered against any :doc:`layer </views/layers>`,
+so it is always available. The view becomes available upon Zope start-up, and is
+available even if you don't run an add-on installer. This is the suggested
approach for logic views which are not theme related.
The ``grok.context(Interface)`` statement means that view is available for every content item:
-you can use it in URL like *http://yoursite/news/newsitem/@@yourviewname* or
-*http://yoursite/news/@@yourviewname* - just incoming self.context parameter changes.
-Alternatively, you could use here some :doc:`content interface </content/types>`
-to make view available for certain content types only.
+You can use it in URL like *http://yoursite/news/newsitem/@@yourviewname* or
+*http://yoursite/news/@@yourviewname* - just the incoming self.context parameter changes.
+Alternatively, you could use the docs here :doc:`content interface </content/types>`
+to make the view available only for certain content types.
Then create *yourcompany.app/yourcompany/app/browser/templates* and add the related template::
@@ -177,7 +188,8 @@ Then create *yourcompany.app/yourcompany/app/browser/templates* and add the rela
</html>
-Another example (empty.pt) which renders only title and description Plone 3 way::
+Another example (empty.pt), which renders only the title and
+description fields in the Plone 3 way::
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:metal="http://xml.zope.org/namespaces/metal"
@@ -197,26 +209,29 @@ Another example (empty.pt) which renders only title and description Plone 3 way:
</html>
-Possible :doc:`slot </templates_css_and_javascripts/template_basics>` options you can fill in
+Possible :doc:`slot </templates_css_and_javascripts/template_basics>`
+options you can use in the template:
* ``main`` - render edit border yourself
* ``content`` - render title your self
* ``content-core`` - title prerendered, Plone version > 4.x
-Now you can access your view with a news folder::
+Now you can access your view within the news folder::
http://localhost:8080/Plone/news/myview
-... or a site root::
+... or on a site root::
http://localhost:8080/Plone/myview
-... or any content item.
+... or on any other content item.
-You can also use @@ notation at the front of the view name to make sure a view is looked up. This
-is used to separate view names from content item names, if these two conflict::
+You can also use the @@ notation at the front of the view name to make
+sure that a view is being looked up. This is used to disambiguate
+between view names and content item names, should these two be in
+conflict::
http://localhost:8080/Plone/news/@@myview
@@ -255,43 +270,45 @@ Example::
.. warning::
- Do not attempt to run any code in __init__() method of a view.
- If this code fails and exception is caused, zope.component machinery
- remaps this as "View not found" exception or traversing error.
- Instead, use a pattern where you have setup() or similar
- method which __call__() or view users explicitly call.
+ Do not attempt to run any code in the __init__() method of a view.
+ If this code fails and an exception is raised, the
+ zope.component machinery remaps this to a "View not found"
+ exception or traversing error.
+ Instead, use a pattern where you have a setup() or similar
+ method which __call__() or view users can explicitly call.
Registering a view
+++++++++++++++++++++
-Zope 3 views are registered in ZCML, XML-based configuration language.
-Usually the configuration file, where the registration done is
+Zope 3 views are registered in ZCML, an XML-based configuration language.
+Usually, the configuration file, where the registration done, is called
*yourapp.package/yourapp/package/browser/configure.zcml*.
-The following example registers a new view
+The following example registers a new view:
-* *for* tells which content receive this view.
- for="*" means that this view can be used for any content. This equals for registering views
- to zope.interface.Interface base class.
+* *for* tells which content types receive this view.
+ for="*" means that this view can be used for any content type. This equals registering views
+ to the zope.interface.Interface base class.
-* *name* is view's name which exposes it to traversing and getMultiAdapter()
- look-ups. If your view's name is "test" then you can render it in browser
- by calling http://yourhost/site/page/@@test
+* *name* is the view's name which exposes it to traversing and getMultiAdapter()
+ look-ups. If your view's name is "test", then you can render it in
+ the browser by calling http://yourhost/site/page/@@test
-* *permission* is permission needed to access the view.
- When HTTP request comes in, the currently logged in user's access rights
+* *permission* is the permission needed to access the view.
+ When an HTTP request comes in, the currently logged in user's access rights
in the current context are checked against this permission.
See :doc:<Security chapter /security/permission_lists.txt>
- for available Plone out-of-the-box permissions. Usually
- you want have *zope2.View*, *cmf.ModifyPortalContent*, *cmf.ManagePortal* or *zope2.Public* here.
+ for available Plone's out-of-the-box permissions. Usually
+ you want have *zope2.View*, *cmf.ModifyPortalContent*,
+ *cmf.ManagePortal* or *zope2.Public* here.
-* *class* is Python dotted name for BrowserView based class which is
- responsible for managing the view. Class __call__() method
+* *class* is a Python dotted name for a class based on BrowserView, which is
+ responsible for managing the view. The Class's __call__() method
is the entry point for view processing and rendering.
-* Note that you need to declare *browser* namespace in your configure.zcml
- to use *browser* configuration directives
+* Note that you need to declare the *browser* namespace in your configure.zcml
+ to use *browser* configuration directives:
.. code-block:: xml
@@ -312,10 +329,11 @@ The following example registers a new view
Relationship between views and templates
++++++++++++++++++++++++++++++++++++++++++
-ZCML <browser:view template=""> will set *index* class attribute.
+The ZCML <browser:view template=""> directive will set the *index*
+class attribute.
-The default view __call__() method will return the value
-returned by self.index() call.
+The default view's __call__() method will return the value
+returned by a call to self.index().
Example::
@@ -346,7 +364,7 @@ is equal to::
class MyView(BrowserView):
pass
-Rendering of the view is done by following::
+Rendering of the view is done by the following::
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
@@ -364,8 +382,8 @@ Rendering of the view is done by following::
Overriding a view template in run-time
++++++++++++++++++++++++++++++++++++++++
-Below is an sample code snipped which allows override of already
-constructed ``ViewPageTemplateFile`` with a chosen file in run-time::
+Below is a sample code snippet which allows you to override an already
+constructed ``ViewPageTemplateFile`` with a chosen file at run-time::
import plone.z3cform
from zope.app.pagetemplate import ViewPageTemplateFile as Zope3PageTemplateFile
@@ -380,8 +398,8 @@ constructed ``ViewPageTemplateFile`` with a chosen file in run-time::
Several templates per view
+++++++++++++++++++++++++++
-You can bind several template per one view and render them in bits.
-This is very useful for reusable templating and when you subclass
+You can bind several templates to one view and render them in bits.
+This is very useful for reusable templating, or when you subclass
your functional views.
Example using five.grok::
@@ -408,15 +426,16 @@ Layers
Views can be registered against a specific layer interface. This means that
views are only looked up if the specific layer is effective.
Since one Zope application server can contain multiple Plone sites, layers
-are used to determine which Python code is effective for which Plone site.
+are used to determine which Python code is in effect for a given Plone site.
-Layer can be be effective when
+A layer can be be effective when
-* certain theme is active
+* a certain theme is active, or
* if a specific add-on product is installed
-You should generally always register your views against a certain layer in your own code.
+You should generally always register your views against a certain
+layer in your own code.
For more information, see
@@ -437,7 +456,8 @@ Zope ViewPageTemplateFile vs. Five ViewPageTemplateFile
* Zope `BrowserView source code <http://svn.zope.org/zope.publisher/trunk/src/zope/publisher/browser.py?rev=101538&view=auto>`_.
* `Five version <http://svn.zope.org/Zope/trunk/src/Products/Five/browser/__init__.py?rev=96262&view=markup>`_. Products.Five is a way
- to stick some of Zope 3 technologies to Zope 2 codebase used by Plone.
+ to access some of Zope 3 technologies from the Zope 2 codebase,
+ which is used by Plone.
Difference in code::
@@ -448,17 +468,18 @@ Difference in code::
from zope.app.pagetemplate import ViewPageTemplateFile
-Difference is that Five version supports
+The difference is that the Five version supports
* Acquisition
* provider: TAL expression
* Other Plone specific TAL expression functions like test()
-* Usually Plone code needs Five version of ViewPageTemplateFile
+* Usually, Plone code needs the Five version of ViewPageTemplateFile.
-* Some subsystems, notably z3c.form package, expect Zope 3 version of ViewPageTemplateFile instances
+* Some subsystems, notably the z3c.form package, expect the Zope 3
+ version of ViewPageTemplateFile instances.
Overriding a view class in a product
@@ -523,10 +544,11 @@ plone.app.users package, creating a custom form which subclasses the original.
Helper views
------------
-Not all views need to return HTML output, or output at all. Views can be used as a helpers
-around in the code to provide APIs to objects. Since views can be overridden using layers,
-view is a natural plug-in point which an add-on product can customize or override
-in a conflict-free manner.
+Not all views need to return HTML output, or output at all. Views can
+be used as a helpers around in the code to provide APIs to
+objects. Since views can be overridden using layers, a view is a
+natural plug-in point which an add-on product can customize or
+override in a conflict-free manner.
View methods are exposed to page templates and such, so you can also call
view methods directly from a page template, besides Python code.
@@ -541,41 +563,49 @@ More information
Historical perspective
=======================
-Often the point of using helper views is that you can have reusable functionality which can be plugged-in as one-line code around the system. Helper views also get around the following limitations:
+Often, the point of using helper views is that you can have reusable
+functionality which can be plugged-in as one-line code around the
+system. Helper views also get around the following limitations:
* TAL security
* Limiting Python expression to one line
* Not being able to import Python modules
-.. note ::
+.. Note ::
- Using RestrictedPython scripts (creating Python through
- Zope Management Interface) and Zope 2 Extension modules is discouraged.
- The same functionality can be achieved with helper views, with
- less potential pitfalls.
+ Using RestrictedPython scripts (creating Python through the
+ Zope Management Interface) and Zope 2 Extension modules is
+ discouraged. The same functionality can be achieved with
+ helper views, with less potential pitfalls.
Reusing view template snippets or embedding another view
-------------------------------------------------------------
To use the same template code several times you can either
-* Create a own BrowserView for it call this view (see *Getting a view* below)
+* Create a separate BrowserView for it and then call this view (see *Getting a view* below)
-* Share a ViewPageTemplate instance between views and using it several times
+* Share a ViewPageTemplate instance between views and using it several times
-.. note::
+.. Note::
- Plone 2.x way, TAL template language macros, are discouraged to provide reusable
- functionality in your add-on product. This is because macros are hardwired
- to TAL template language and referring them outside templates is difficult.
- Also, if you ever need to mix or change the template language, you can
- do it easily when templates are a feature of a pure Python based view and not vice versa.
+ The Plone 2.x way of doing this with TAL template language
+ macros is discouraged to provide reusable functionality in
+ your add-on product. This is because macros are hardwired
+ to the TAL template language, and referring to them outside
+ templates is difficult.
+ Also, if you ever need to change the template language, or mix
+ in other template languages, you can do it much more easily when
+ templates are a feature of a pure Python based view, and not
+ vice versa.
-Here is an example how to have a view snippet which can be used subclasses of a base view class.
-Subclasses can refer to this template in any point of the view rendering, making it possible
-for subclasses to have fine tuned control over how the template snippet is represented.
+Here is an example of how to have a view snippet which can be used by
+subclasses of a base view class. Subclasses can refer to this template
+at any point of the view rendering, making it possible for subclasses
+to have fine tuned control over how the template snippet is
+represented.
Related Python code::
@@ -599,8 +629,9 @@ Related Python code::
"""
return self.summary_template()
-Then you can render summary template in the main template associated with ProductCardView,
-by calling ``renderSummary()`` method and TAL non-escaping HTML embedding.
+Then you can render the summary template in the main template
+associated with ProductCardView by calling the ``renderSummary()`` method
+and TAL non-escaping HTML embedding.
.. code-block:: html
@@ -612,8 +643,10 @@ by calling ``renderSummary()`` method and TAL non-escaping HTML embedding.
<div tal:condition="python:context.Description().decode('utf-8') != u'None'" tal:replace="structure context/Description" />
</div>
-And the summarybox.pt itself is just HTML code without Plone decoration frame (main_template/master etc. macros).
-Make sure that you declare i18n:domain again or the strings in this template are not translated.
+The summarybox.pt itself is just a piece of HTML code without the
+Plone decoration frame (main_template/master etc. macros). Make sure
+that you declare the i18n:domain again, or the strings in this
+template will not be translated.
.. code-block:: html
@@ -624,20 +657,22 @@ Make sure that you declare i18n:domain again or the strings in this template are
Accessing a view instance in code
-----------------------------------
-You need to get access to view in your code if you are
+You need to get access to the view in your code if you are
+
+* Calling a view from inside another view, or
+
+* Calling a view from your unit test code
-* Calling a view from inside another view
-* Calling a view from unit test code
+Below are two different approaches for that.
-Below are two different approach.
By using getMultiAdapter()
==========================
This is the most efficient way in Python.
-Example
+Example:
.. code-block:: python
@@ -657,10 +692,11 @@ Example
By using traversing
===================
-Traversing is slower than direct getMultiAdapter() call.
-However, traversing is available in templates and RestrictedPython modules easily.
+Traversing is slower than directly calling getMultiAdapter().
+However, traversing is readily available in templates and
+RestrictedPython modules.
-Example
+Example:
.. code-block:: python
@@ -681,7 +717,8 @@ Example
return view
-You can also do direct view looks up and method calls in template by using @@ notation in traversing.
+You can also do direct view look ups and method calls in your template
+by using the @@ notation in traversing.
.. code-block:: html
@@ -693,9 +730,10 @@ You can also do direct view looks up and method calls in template by using @@ n
Use a skin based template in a Five view
========================================
-Use aq_acquire(object, template_name)
+Use aq_acquire(object, template_name).
-Example: Get an object by its path and render it using its default template in the current context.
+Example: Get an object by its path and render it using its default
+template in the current context.
.. code-block:: python
@@ -731,7 +769,7 @@ This is useful for debugging purposes::
Listing all views of certain type
=================================
-How to filter out views which provide certain interface.
+How to filter out views which provide a certain interface::
from plone.app.customerize import registration
from zope.publisher.interfaces.browser import IBrowserRequest
@@ -742,30 +780,33 @@ How to filter out views which provide certain interface.
# Filter out all classes which do not filter a certain interface
views = [ view.factory for view in views if IBlocksView.implementedBy(view.factory) ]
+
Default view of a content item
-------------------------------
-Objects has views for "default", view, edit, and so on.
+Objects have views for "default", view, edit, and so on.
-The distinction between *default* and *view* views are that for files,
+The distinction between the *default* and *view* views are that for files,
the default can be download.
+
The default view...
* This view is configured in :doc:`portal_types </content/types>`.
-* This view is rendered when content item is called - even though
- they are objects, they have ``__call__()`` Python method defined.
+* This view is rendered when a content item is called - even though
+ they are objects, they have the ``__call__()`` Python method
+ defined.
-If you explicitly need to get content item view for page rendering,
-you can do it::
+If you explicitly need to get a content item's view for page
+rendering, you can do it::
def viewURLFor(item):
cdtate = getMultiAdapter((item, item.REQUEST), name='plone_context_state)
return cstate.view_url()
-More info
+More info::
* :doc:`Context helpers and utilities </misc/context>`
@@ -779,25 +820,25 @@ Views and magical acquisition
This is really nasty stuff. If this were not be a public document I'd
use more harsh words here.
-In Plone 3, the following will lead the very hard to debug errors.
+In Plone 3, the following will lead to errors which are very hard to debug.
Views will automatically assign themselves as a parent for all member variables.
-E.g. you have Basket content item with absolute_url() of ::
+E.g. you have a Basket content item with absolute_url() of ::
http://localhost:9666/isleofback/sisalto/matkasuunnitelmat/d59ca034c50995d6a77cacbe03e718de
-Then if you use this object in view code member variable assignment...
+Then if you use this object in a view code's member variable assignment...
::
self.basket = my_basket
-... this will mess up Basket content item acquisition chain::
+... this will mess up the Basket content item's acquisition chain::
<Basket at /isleofback/sisalto/yritykset/katajamaan_taksi/d59ca034c50995d6a77cacbe03e718de>
-One workaround to avoid this mess it to put a member variable inside a Python array
+One workaround to avoid this mess is to put a member variable inside a Python array
and create an accessor method to read it when needed::

0 comments on commit 7ff6dae

Please sign in to comment.
Something went wrong with that request. Please try again.