Index: main/waeup.kofa/trunk/docs/source/userdocs/datacenter.rst
===================================================================
--- main/waeup.kofa/trunk/docs/source/userdocs/datacenter.rst	(revision 12857)
+++ main/waeup.kofa/trunk/docs/source/userdocs/datacenter.rst	(revision 12858)
@@ -13,9 +13,9 @@
 Kofa's persistent data are stored in a native object database designed for the Python programming language, the so-called ZODB_. An object database stores objects with attributes and not records as rows with columns in tables. These persistent objects can hold any kind of information in attributes and must not adhere to a specific schema like records in tables of a relational database.
 
-The ZODB_ also supports a hierarchical, treelike storage of objects. Objects can contain other objects if they are declared as containers. Objects are stored like folders and files in a filesystem. This makes the object handling very fast and transparent because we can access objects, or more precisely views of objects, by indicating their path in the database, i.e. by traversing the database tree to find an object. Furthermore, we are accessing the views of objects through a web browser by entering a URL (Uniform Resource Locator). This publication path corresponds more or less to the traversal path of our objects. In Kofa the path always contains the object identifiers of all objects which are passed when traversing the database tree. Example:
+The ZODB_ also supports a hierarchical, treelike storage of objects. Objects can contain other objects if they are declared as containers. Objects are stored like folders and files in a filesystem. This makes the object handling very fast and transparent because we can access objects, or more precisely views of objects, by indicating their path in the database, i.e. by traversing the database tree to the object's location. Furthermore, we are accessing the views of objects through a web browser by entering a URL (Uniform Resource Locator). This publication path corresponds more or less to the traversal path of our objects. In Kofa the path always contains the object identifiers of all objects which are passed when traversing the database tree. Example:
 
 https://kofa-demo.waeup.org/students/K1000000/studycourse/100/DCO
 
-is the URL which requests a display view of a course ticket with id 'DCO'. This object is stored in a study level container object with id '100', stored in a study course container object with id 'studycourse', stored in the student container object with id 'K1000000', stored in the students root container, stored in the root container of the application, stored in the root of the database itself.
+is the URL which requests a display view of a course ticket with id ``DCO``. This object is stored in a study level container object with id ``100``, stored in a study course container object with id ``studycourse``, stored in the student container object with id ``K1000000``, stored in the students root container, stored in the root container of the application, stored in the root of the database itself.
 
 This kind of storage requires that each object gets a unique object identifier (object id) within its container. The id string is visible in the browser address bar. Though it's technically possible for ids to contain spaces or slashes we do not allow these kinds of special characters in object ids to facilitate the readability of URLs.
@@ -26,5 +26,10 @@
 ===========
 
-Regular data exporters (1) collect objects from specific containers, (2) iterate over the collected objects, (3) extract and mangle information from each object, (4) write the information of each object into a row of a CSV file and (5) finally provide the file for download. The CSV file is neither stored in the database nor archived in the filesystem. (3) and (4) is a flattening of the hierarchical data structure, i.e. a mapping of objects to flat relational data stored in a CSV table. The extracted information must not necessarily be based only on static attributes of the collected object. The data, finally stored in the CSV file, can also be derived from parent or child objects, or dynamically computed by the object's methods and property attributes. These methods and properties can retrieve information from everywhere in the portal's database.
+Regular data exporters (1) collect objects from specific containers, (2) iterate over the collected objects, (3) extract and mangle information from each object, (4) write the information of each object into a row of a CSV file and (5) finally provide the file for download. The CSV file is neither stored in the database nor archived in the filesystem. (3) and (4) means a flattening of the hierarchical data structure, i.e. a mapping of objects to flat relational data to be stored in a CSV table. The extracted information must not necessarily be based only on static attributes of the collected object. The data, finally stored in the CSV file, can also be derived from parent or child objects, or dynamically computed by the object's methods and property attributes. These methods and properties can retrieve information from everywhere in the portal's database.
+
+In the following we list all exporter classes including the two attributes and a method description. The `fields` attribute contain the column titles of the export file. These are not necessarily only attributes of the exported objects. The `title` attribute unveils the name of the exporter under which this exporter will be displayed in the user interface. The `mangle_value()` method shows how some of fields are being dynamically computed.
+
+Academic Section Exporters
+--------------------------
 
 .. autoclass:: waeup.kofa.university.export.FacultyExporter()
@@ -33,8 +38,42 @@
   .. autoattribute:: waeup.kofa.university.export.FacultyExporter.fields
   .. autoattribute:: waeup.kofa.university.export.FacultyExporter.title
-
   .. automethod:: waeup.kofa.university.export.FacultyExporter.mangle_value()
 
 
+.. autoclass:: waeup.kofa.university.export.DepartmentExporter()
+  :noindex:
+
+  .. autoattribute:: waeup.kofa.university.export.DepartmentExporter.fields
+  .. autoattribute:: waeup.kofa.university.export.DepartmentExporter.title
+  .. automethod:: waeup.kofa.university.export.DepartmentExporter.mangle_value()
+
+.. autoclass:: waeup.kofa.university.export.CourseExporter()
+  :noindex:
+
+  .. autoattribute:: waeup.kofa.university.export.CourseExporter.fields
+  .. autoattribute:: waeup.kofa.university.export.CourseExporter.title
+  .. automethod:: waeup.kofa.university.export.CourseExporter.mangle_value()
+
+.. autoclass:: waeup.kofa.university.export.CertificateExporter()
+  :noindex:
+
+  .. autoattribute:: waeup.kofa.university.export.CertificateExporter.fields
+  .. autoattribute:: waeup.kofa.university.export.CertificateExporter.title
+  .. automethod:: waeup.kofa.university.export.CertificateExporter.mangle_value()
+
+.. autoclass:: waeup.kofa.university.export.CertificateCourseExporter()
+  :noindex:
+
+  .. autoattribute:: waeup.kofa.university.export.CertificateCourseExporter.fields
+  .. autoattribute:: waeup.kofa.university.export.CertificateCourseExporter.title
+  .. automethod:: waeup.kofa.university.export.CertificateCourseExporter.mangle_value()
+
+
+Application Section Exporters
+-----------------------------
+
+
+Student Section Exporters
+-------------------------
 
 
Index: main/waeup.kofa/trunk/src/waeup/kofa/browser/captcha.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/browser/captcha.py	(revision 12857)
+++ main/waeup.kofa/trunk/src/waeup/kofa/browser/captcha.py	(revision 12858)
@@ -286,6 +286,6 @@
 
         The ``error_code`` can be taken from a previously fetched
-        :class:``CaptchaResponse`` instance (as returned by
-        :meth:``verify``). If it is not ``None``, it might be
+        :class:`CaptchaResponse` instance (as returned by
+        :meth:`verify`). If it is not ``None``, it might be
         displayed inside the generated captcha box (in human readable
         form).
Index: main/waeup.kofa/trunk/src/waeup/kofa/university/export.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/university/export.py	(revision 12857)
+++ main/waeup.kofa/trunk/src/waeup/kofa/university/export.py	(revision 12858)
@@ -24,6 +24,7 @@
 from waeup.kofa.utils.batching import ExporterBase
 
+
 class FacultyExporter(grok.GlobalUtility, ExporterBase):
-    """The FacultyExporter exports all faculties in the 'faculties'
+    """The Faculty Exporter exports all faculties in the 'faculties'
     container. This is the only place where faculties are stored.
     """
@@ -36,5 +37,6 @@
 
     def mangle_value(self, value, name, context=None):
-        """The users_with_local_roles column contains Python expression like:
+        """The mangler computes the users_with_local_roles value which
+        is a Python expression like:
 
         ``[{'user_name': u'bob', 'local_role': u'bobsrole'},
@@ -66,11 +68,13 @@
         return self.export(faculties.values(), filepath)
 
+
 class DepartmentExporter(FacultyExporter, grok.GlobalUtility):
-    """Exporter for departments.
+    """The Department Exporter exports all departments stored in the faculty
+    containers. The exporter iterates over all faculties and then over all
+    departments inside each faculty container.
     """
     grok.implements(ICSVExporter)
     grok.name('departments')
 
-    #: Fieldnames considered by this exporter
     fields = ('code', 'faculty_code', 'title', 'title_prefix',
         'users_with_local_roles')
@@ -79,5 +83,7 @@
 
     def mangle_value(self, value, name, context=None):
-        """Hook for mangling values in derived classes
+        """The mangler additionally computes the faculty_code value
+        which is the code (= object id) of the faculty that hosts
+        the department.
         """
         if name == 'faculty_code':
@@ -101,18 +107,18 @@
 
 class CourseExporter(FacultyExporter, grok.GlobalUtility):
-    """Exporter for courses.
+    """The Course Exporter exports all courses in the database. It iterates
+    over all departments and faculties.
     """
     grok.implements(ICSVExporter)
     grok.name('courses')
 
-    #: Fieldnames considered by this exporter
     fields = ('code', 'faculty_code', 'department_code', 'title', 'credits',
               'passmark', 'semester', 'users_with_local_roles', 'former_course')
 
-    #: The title under which this exporter will be displayed
     title = _(u'Courses')
 
     def mangle_value(self, value, name, context=None):
-        """
+        """The mangler additionally computes the department_code value
+        which is the code of the department that offers the course.
         """
         if name == 'users_with_local_roles':
@@ -137,5 +143,4 @@
     def export_all(self, site, filepath=None):
         """Export courses into filepath as CSV data.
-
         If `filepath` is ``None``, a raw string with CSV data is returned.
         """
@@ -148,11 +153,12 @@
         return self.close_outfile(filepath, outfile)
 
+
 class CertificateExporter(CourseExporter, grok.GlobalUtility):
-    """Exporter for courses.
+    """The Certificate Exporter exports all certificates in the database.
+    It iterates over all departments and faculties.
     """
     grok.implements(ICSVExporter)
     grok.name('certificates')
 
-    #: Fieldnames considered by this exporter
     fields = ('code', 'faculty_code', 'department_code', 'title', 'study_mode',
               'start_level', 'end_level', 'application_category', 'ratio',
@@ -162,10 +168,15 @@
               'users_with_local_roles')
 
-    #: The title under which this exporter will be displayed
     title = _(u'Certificates')
 
+    def mangle_value(self, value, name, context=None):
+        """The mangler additionally computes the department_code value
+        which is the code of the department that offers the certificate.
+        """
+        return super(CertificateExporter, self).mangle_value(
+            value, name, context)
+
     def export_all(self, site, filepath=None):
         """Export certificates into filepath as CSV data.
-
         If `filepath` is ``None``, a raw string with CSV data is returned.
         """
@@ -178,19 +189,26 @@
         return self.close_outfile(filepath, outfile)
 
+
 class CertificateCourseExporter(CourseExporter, grok.GlobalUtility):
-    """Exporter for courses.
+    """The Certificate Course Exporter exports all certificate courses
+    (:class:`CertificateCourse
+    <waeup.kofa.university.certificate.CertificateCourse>` instances) in
+    the database. It iterates over all departments and faculties.
     """
     grok.implements(ICSVExporter)
     grok.name('certificate_courses')
 
-    #: Fieldnames considered by this exporter
     fields = ('course', 'faculty_code', 'department_code', 'certificate_code',
               'level', 'mandatory')
 
-    #: The title under which this exporter will be displayed
     title = _(u'Courses in Certificates')
 
     def mangle_value(self, value, name, context=None):
-        """Hook for mangling values in derived classes
+        """The mangler computes the codes of the faculty, the department and
+        the certificate which require the course. It also exports the
+        course code.
+
+        .. note:: The course must not necessarily be offered by the same
+                  department.
         """
         if name == 'faculty_code':
@@ -214,5 +232,4 @@
     def export_all(self, site, filepath=None):
         """Export certificate courses into filepath as CSV data.
-
         If `filepath` is ``None``, a raw string with CSV data is returned.
         """
