source: main/waeup.sirp/trunk/src/waeup/sirp/students/student.py @ 7098

Last change on this file since 7098 was 7097, checked in by Henrik Bettermann, 13 years ago

Implement StudentFileNameChooser? and StudentFileStoreHandler?.

Define viewlet manager FileManager? in viewlets.py and define display and upload viewlets for the StudentClearanceDisplayFormPage?.

Also define image views. Since these views are part of the viewlets they are defined also in the viewlets module. In browser.py we only add an empty files_changed list attribute to the StudentClearanceManageFormPage?. This will be needed for logging (to be done).

  • Property svn:keywords set to Id
File size: 8.4 KB
Line 
1## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
2## This program is free software; you can redistribute it and/or modify
3## it under the terms of the GNU General Public License as published by
4## the Free Software Foundation; either version 2 of the License, or
5## (at your option) any later version.
6##
7## This program is distributed in the hope that it will be useful,
8## but WITHOUT ANY WARRANTY; without even the implied warranty of
9## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10## GNU General Public License for more details.
11##
12## You should have received a copy of the GNU General Public License
13## along with this program; if not, write to the Free Software
14## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15##
16"""
17Container for the various objects owned by students.
18"""
19import os
20import grok
21from grok import index
22from zope.component.interfaces import IFactory
23from zope.interface import implementedBy
24from hurry.workflow.interfaces import IWorkflowState, IWorkflowInfo
25from zope.securitypolicy.interfaces import IPrincipalRoleManager
26from waeup.sirp.interfaces import (
27    IObjectHistory, IUserAccount, IFileStoreNameChooser, IFileStoreHandler)
28from waeup.sirp.image import WAeUPImageFile
29from waeup.sirp.imagestorage import DefaultFileStoreHandler
30from waeup.sirp.students.interfaces import (
31    IStudent, IStudentNavigation, IStudentClearanceEdit,
32    IStudentPersonalEdit)
33from waeup.sirp.students.studycourse import StudentStudyCourse
34from waeup.sirp.students.payments import StudentPaymentsContainer
35from waeup.sirp.students.accommodation import StudentAccommodation
36from waeup.sirp.utils.helpers import attrs_to_fields, get_current_principal
37from waeup.sirp.students.utils import generate_student_id
38
39class Student(grok.Container):
40    """This is a student container for the various objects
41    owned by students.
42    """
43    grok.implements(IStudent, IStudentNavigation,
44        IStudentPersonalEdit, IStudentClearanceEdit)
45    grok.provides(IStudent)
46
47    def __init__(self):
48        super(Student, self).__init__()
49        # The site doesn't exist in unit tests
50        try:
51            students = grok.getSite()['students']
52            self.student_id = generate_student_id(students,'?')
53        except TypeError:
54            self.student_id = u'Z654321'
55        self.password = None
56       
57        return
58
59    def loggerInfo(self, ob_class, comment=None):
60        target = self.__name__
61        return grok.getSite()['students'].logger_info(ob_class,target,comment)
62
63    @property
64    def state(self):
65        state = IWorkflowState(self).getState()
66        return state
67
68    @property
69    def history(self):
70        history = IObjectHistory(self)
71        return history
72
73    def getStudent(self):
74        return self
75
76    @property
77    def certificate(self):
78        cert = getattr(self.get('studycourse', None), 'certificate', None)
79        return cert
80
81    @property
82    def current_session(self):
83        cert = getattr(self.get('studycourse', None), 'current_session', None)
84        return cert
85
86# Set all attributes of Student required in IStudent as field
87# properties. Doing this, we do not have to set initial attributes
88# ourselves and as a bonus we get free validation when an attribute is
89# set.
90Student = attrs_to_fields(Student)
91
92class StudentFactory(grok.GlobalUtility):
93    """A factory for students.
94    """
95    grok.implements(IFactory)
96    grok.name(u'waeup.Student')
97    title = u"Create a new student.",
98    description = u"This factory instantiates new student instances."
99
100    def __call__(self, *args, **kw):
101        return Student()
102
103    def getInterfaces(self):
104        return implementedBy(Student)
105
106@grok.subscribe(IStudent, grok.IObjectAddedEvent)
107def handle_student_added(student, event):
108    """If a student is added all subcontainers are automatically added
109    and the transition create is fired. The latter produces a logging message.
110    """
111    student.clearance_locked = True
112    studycourse = StudentStudyCourse()
113    student['studycourse'] = studycourse
114    payments = StudentPaymentsContainer()
115    student['payments'] = payments
116    accommodation = StudentAccommodation()
117    student['accommodation'] = accommodation
118    # Assign global student role for new student
119    account = IUserAccount(student)
120    account.roles = ['waeup.Student']
121    # Assign local StudentRecordOwner role
122    role_manager = IPrincipalRoleManager(student)
123    role_manager.assignRoleToPrincipal(
124        'waeup.local.StudentRecordOwner', student.student_id)
125    IWorkflowInfo(student).fireTransition('create')
126    return
127
128@grok.subscribe(IStudent, grok.IObjectRemovedEvent)
129def handle_student_removed(student, event):
130    """If a student is removed a message is logged.
131    """
132    comment = 'Student record removed'
133    target = student.student_id
134    # In some tests we don't have a principal
135    try:
136        user = get_current_principal().id
137    except (TypeError, AttributeError):
138        return
139    grok.getSite()['students'].logger.info('%s - %s - %s' % (
140        user, target, comment))
141    return
142
143#: The file id marker for student files
144STUDENT_FILE_STORE_NAME = 'file-student'
145
146class StudentFileNameChooser(grok.Adapter):
147    """A file id chooser for :class:`Applicant` objects.
148
149    `context` is an :class:`Applicant` instance.
150
151    The :class:`ApplicantImageNameChooser` can build/check file ids
152    for :class:`Applicant` objects suitable for use with
153    :class:`ExtFileStore` instances. The delivered file_id contains
154    the file id marker for :class:`Applicant` object and the
155    registration number or access code of the context applicant. Also
156    the name of the connected applicant container will be part of the
157    generated file id.
158
159    This chooser is registered as an adapter providing
160    :class:`waeup.sirp.interfaces.IFileStoreNameChooser`.
161
162    File store name choosers like this one are only convenience
163    components to ease the task of creating file ids for applicant
164    objects. You are nevertheless encouraged to use them instead of
165    manually setting up filenames for applicants.
166
167    .. seealso:: :mod:`waeup.sirp.imagestorage`
168
169    """
170    grok.context(IStudent)
171    grok.implements(IFileStoreNameChooser)
172
173    def checkName(self, name=None, attr=None):
174        """Check whether the given name is a valid file id for the context.
175
176        Returns ``True`` only if `name` equals the result of
177        :meth:`chooseName`.
178
179        """
180        return name == self.chooseName()
181
182    def chooseName(self, name=None, attr=None):
183        """Get a valid file id for student context.
184
185        *Example:*
186
187        For a student with student id ``'A123456'`` and
188        with attr ``'nice_image'`` stored in
189        the students container this chooser would create:
190
191          ``'__file-student__students/A/A123456/nice_image_A123456.jpg'``
192
193        meaning that the nice image of this applicant would be
194        stored in the site-wide file storage in path:
195
196          ``students/A/A123456/nice_image_A123456.jpg``
197
198        """
199        first_character = self.context.student_id[0]
200        marked_filename = '__%s__%s/%s/%s_%s.jpg' % (
201            STUDENT_FILE_STORE_NAME, first_character,
202            self.context.student_id, attr, self.context.student_id)
203        return marked_filename
204
205
206class StudentFileStoreHandler(DefaultFileStoreHandler, grok.GlobalUtility):
207    """Student specific file handling.
208
209    This handler knows in which path in a filestore to store student
210    files and how to turn this kind of data into some (browsable)
211    file object.
212
213    It is called from the global file storage, when it wants to
214    get/store a file with a file id starting with
215    ``__file-student__`` (the marker string for student files).
216
217    Like each other file store handler it does not handle the files
218    really (this is done by the global file store) but only computes
219    paths and things like this.
220    """
221    grok.implements(IFileStoreHandler)
222    grok.name(STUDENT_FILE_STORE_NAME)
223
224    def pathFromFileID(self, store, root, file_id):
225        """All applicants images are filed in directory ``applicants``.
226        """
227        marker, filename, basename, ext = store.extractMarker(file_id)
228        return os.path.join(root, 'students', filename)
229
230    def createFile(self, store, root, filename, file_id, file):
231        """Create a browsable file-like object.
232        """
233        # possible other actions: check for jpeg format
234        path = self.pathFromFileID(store, root, file_id)
235        return file, path, WAeUPImageFile(filename, file_id)
Note: See TracBrowser for help on using the repository browser.