Index: main/waeup.ikoba/trunk/src/waeup/ikoba/browser/templates/widgets.pt
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/browser/templates/widgets.pt	(revision 12118)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/browser/templates/widgets.pt	(revision 12119)
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser.py	(revision 12118)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser.py	(revision 12119)
@@ -47,4 +47,5 @@
 from waeup.ikoba.browser.interfaces import ICaptchaManager
 from waeup.ikoba.mandates.mandate import PasswordMandate
+from waeup.ikoba.widgets.hrefwidget import HREFDisplayWidget
 from waeup.ikoba.utils.helpers import get_current_principal, to_timezone, now
 from waeup.ikoba.customers.interfaces import (
@@ -68,6 +69,6 @@
     if changed_fields:
         changed_fields = reduce(lambda x,y: x+y, changed_fields.values())
-    if 'product' in changed_fields and data['product'] is not None:
-        view.context.last_product_id = data['product'].product_id
+    if 'product_object' in changed_fields and data['product_object'] is not None:
+        view.context.last_product_id = data['product_object'].product_id
         notify(grok.ObjectModifiedEvent(view.context))
     fields_string = ' + '.join(changed_fields)
@@ -1155,6 +1156,10 @@
     @property
     def form_fields(self):
-        return grok.AutoFields(self.context.form_fields_interface).omit(
+        form_fields = grok.AutoFields(self.context.form_fields_interface).omit(
             'last_transition_date')
+        for field in form_fields:
+            if field.__name__.endswith('_object'):
+                form_fields[field.__name__].custom_widget = HREFDisplayWidget
+        return form_fields
 
     @property
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py	(revision 12118)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py	(revision 12119)
@@ -288,5 +288,5 @@
         )
 
-    product = schema.Choice(
+    product_object = schema.Choice(
         title = _(u'Product'),
         source = ConCatProductSource(),
@@ -300,5 +300,5 @@
     """
 
-    product = schema.Choice(
+    product_object = schema.Choice(
         title = _(u'Product'),
         source = ConCatProductSource(),
@@ -312,5 +312,5 @@
     """
 
-    document = schema.Choice(
+    document_object = schema.Choice(
         title = _(u'Document'),
         source = CustomerDocumentSource(),
@@ -324,5 +324,5 @@
     """
 
-    product = schema.Choice(
+    product_object = schema.Choice(
         title = _(u'Product'),
         source = ConCatProductSource(),
@@ -330,5 +330,5 @@
         )
 
-    document = schema.Choice(
+    document_object = schema.Choice(
         title = _(u'Document'),
         source = CustomerDocumentSource(),
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_browser.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_browser.py	(revision 12118)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_browser.py	(revision 12119)
@@ -1074,5 +1074,5 @@
         self.browser.getLink("c102").click()
         self.browser.getLink("Manage").click()
-        self.browser.getControl(name="form.product").value = ['SAM']
+        self.browser.getControl(name="form.product_object").value = ['SAM']
         self.browser.getControl(name="form.title").value = 'My second contract'
         self.browser.getControl("Save").click()
@@ -1134,5 +1134,4 @@
         contract = self.customer['contracts']['c102']
         # Contract can be edited ...
-        self.browser.getLink("c102").click()
         self.browser.open(self.contracts_path + '/c102/edit')
         #self.browser.getLink("Edit").click()
@@ -1148,5 +1147,5 @@
         # So far last_product_id is None.
         self.assertTrue(self.customer['contracts']['c102'].last_product_id is None)
-        self.browser.getControl(name="form.product").value = ['SAM']
+        self.browser.getControl(name="form.product_object").value = ['SAM']
         self.browser.getControl("Save").click()
         # Document is a required field on edit form page.
@@ -1157,6 +1156,6 @@
         IWorkflowState(self.document).setState(SUBMITTED)
         self.browser.open(self.contracts_path + '/c102/edit')
-        self.browser.getControl(name="form.product").value = ['SAM']
-        self.browser.getControl(name="form.document").value = ['d101']
+        self.browser.getControl(name="form.product_object").value = ['SAM']
+        self.browser.getControl(name="form.document_object").value = ['d101']
         self.browser.getControl(name="form.title").value = 'My second contract'
         self.browser.getControl("Save").click()
@@ -1165,6 +1164,6 @@
         self.assertEqual(self.customer['contracts']['c102'].last_product_id, 'SAM')
         self.assertEqual(contract.title, 'My second contract')
-        self.assertEqual(contract.product, self.product)
-        self.assertEqual(contract.document, self.document)
+        self.assertEqual(contract.product_object, self.product)
+        self.assertEqual(contract.document_object, self.document)
         # Saving the form again does not unset last_product_id
         self.browser.getControl(name="form.title").value = 'My third contract'
@@ -1174,4 +1173,10 @@
         self.browser.getLink("View").click()
         self.assertEqual(self.browser.url, self.contracts_path + '/c102/index')
+        # An href attribute is referring to the document and product objects
+        self.assertTrue('<a href="http://localhost/app/products/SAM">SAM -'
+            in self.browser.contents)
+        self.assertTrue(
+            '<a href="http://localhost/app/customers/K1000000/documents/d101">d101 -'
+            in self.browser.contents)
         # Customer can submit the form. The form is also saved.
         self.browser.getLink("Edit").click()
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/widgets/hrefwidget.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/widgets/hrefwidget.py	(revision 12119)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/widgets/hrefwidget.py	(revision 12119)
@@ -0,0 +1,36 @@
+## $Id: htmlwidget.py 11949 2014-11-13 14:40:27Z henrik $
+##
+## Copyright (C) 2012 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""A widget that renders a persistent object title inside an anchor element
+referring to the object.
+"""
+import grok
+from zope.formlib.widget import DisplayWidget
+
+
+class HREFDisplayWidget(DisplayWidget):
+
+    def __call__(self):
+        if self._renderedValueSet():
+            title = getattr(self._data, 'title', '')
+            name = getattr(self._data, '__name__', '')
+            if not name:
+                return ''
+            url = grok.url(self.request, self._data)
+        else:
+            return ''
+        return '<a href="%s">%s - %s</a>' % (url, name, title)
