Ignore:
Timestamp:
12 Nov 2011, 22:30:27 (13 years ago)
Author:
Henrik Bettermann
Message:

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).

Location:
main/waeup.sirp/trunk/src/waeup/sirp/students
Files:
4 added
3 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py

    r7068 r7097  
    470470    title = 'Clearance Data'
    471471    pnav = 4
     472    files_changed = []
    472473
    473474    form_fields['date_of_birth'].custom_widget = FriendlyDateWidget('le-year')
  • main/waeup.sirp/trunk/src/waeup/sirp/students/student.py

    r7062 r7097  
    1717Container for the various objects owned by students.
    1818"""
     19import os
    1920import grok
    2021from grok import index
     
    2324from hurry.workflow.interfaces import IWorkflowState, IWorkflowInfo
    2425from zope.securitypolicy.interfaces import IPrincipalRoleManager
    25 from waeup.sirp.interfaces import IObjectHistory, IUserAccount
     26from waeup.sirp.interfaces import (
     27    IObjectHistory, IUserAccount, IFileStoreNameChooser, IFileStoreHandler)
     28from waeup.sirp.image import WAeUPImageFile
     29from waeup.sirp.imagestorage import DefaultFileStoreHandler
    2630from waeup.sirp.students.interfaces import (
    2731    IStudent, IStudentNavigation, IStudentClearanceEdit,
     
    136140        user, target, comment))
    137141    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)
  • main/waeup.sirp/trunk/src/waeup/sirp/students/viewlets.py

    r6687 r7097  
    11import grok
     2from zope.component import getUtility
    23from zope.interface import Interface
    3 from waeup.sirp.interfaces import IWAeUPObject
     4from waeup.sirp.interfaces import (
     5    IWAeUPObject, IExtFileStore, IFileStoreNameChooser)
     6from waeup.sirp.utils.helpers import string_from_bytes, file_size
     7from waeup.sirp.browser import DEFAULT_IMAGE_PATH
     8from waeup.sirp.students.browser import (
     9    StudentClearanceDisplayFormPage, StudentClearanceManageFormPage)
    410
    511grok.context(IWAeUPObject) # Make IWAeUPObject the default context
     
    190196        rel_link = '/students/%s' % self.request.principal.id
    191197        return self.view.application_url() + rel_link
     198
     199def handle_img_upload(upload, context, view, max_size, attr=None):
     200    """Handle upload of applicant image.
     201
     202    Returns `True` in case of success or `False`.
     203
     204    Please note that file pointer passed in (`upload`) most probably
     205    points to end of file when leaving this function.
     206    """
     207    size = file_size(upload)
     208    if size > max_size:
     209        view.flash('Uploaded image is too big!')
     210        return False
     211    upload.seek(0) # file pointer moved when determining size
     212    store = getUtility(IExtFileStore)
     213    file_id = IFileStoreNameChooser(context).chooseName(attr=attr)
     214    store.createFile(file_id, upload)
     215    return True
     216
     217class FileManager(grok.ViewletManager):
     218    """Viewlet manager for uploading files, preferably scanned images.
     219    """
     220    grok.name('files')
     221
     222class FileDisplay(grok.Viewlet):
     223    """Base file display viewlet.
     224    """
     225    grok.baseclass()
     226    grok.viewletmanager(FileManager)
     227    grok.view(StudentClearanceDisplayFormPage)
     228    grok.template('filedisplay')
     229    grok.order(1)
     230    grok.require('waeup.viewStudent')
     231    label = u'Some Text:'
     232    img_src = u'filename.jpg'
     233    attr = None
     234
     235class FileUpload(FileDisplay):
     236    """Base upload viewlet.
     237    """
     238    grok.baseclass()
     239    grok.viewletmanager(FileManager)
     240    grok.view(StudentClearanceManageFormPage)
     241    grok.template('fileupload')
     242    grok.require('waeup.manageStudents')
     243    mus = 1024 * 150
     244    input_name = u'form.filename'
     245
     246    def update(self):
     247        self.max_upload_size = string_from_bytes(self.mus)
     248        upload = self.request.form.get(self.input_name, None)
     249        if upload:
     250            # We got a fresh upload
     251            file_changed = handle_img_upload(
     252                upload, self.context, self.view, self.mus, self.attr)
     253            if file_changed is False:  # False is not None!
     254                self.redirect(self.view.url(self.context))
     255                return # error during image upload. Ignore other values
     256            else:
     257                self.view.files_changed += self.img_src
     258        return
     259
     260class BirthCertificateDisplay(FileDisplay):
     261    """Birth Certificate upload viewlet.
     262    """
     263    grok.order(1)
     264    label = u'Birth Certificate:'
     265    img_src = u'birth_certificate.jpg'
     266    attr = u'birth_certificate'
     267
     268class BirthCertificateUpload(FileUpload):
     269    """Birth Certificate upload viewlet.
     270    """
     271    grok.order(1)
     272    label = u'Birth Certificate:'
     273    mus = 1024 * 150
     274    img_src = u'birth_certificate.jpg'
     275    input_name = u'form.birth_certificate'
     276    attr = u'birth_certificate'
     277
     278class Image(grok.View):
     279    """Renders image for students.
     280    """
     281    grok.name('none.jpg')
     282    grok.view(StudentClearanceManageFormPage)
     283    grok.require('waeup.viewStudent')
     284    grok.baseclass()
     285    attr = None
     286
     287    def render(self):
     288        # A filename chooser turns a context into a filename suitable
     289        # for file storage.
     290        image = getUtility(IExtFileStore).getFileByContext(
     291            self.context, attr=self.attr)
     292        self.response.setHeader(
     293            'Content-Type', 'image/jpeg')
     294        if image is None:
     295            # show placeholder image
     296            return open(DEFAULT_IMAGE_PATH, 'rb').read()
     297        return image
     298
     299class BirthCertificateImage(Image):
     300    """Renders birth certificate.
     301    """
     302    grok.name('birth_certificate.jpg')
     303    attr = u'birth_certificate'
Note: See TracChangeset for help on using the changeset viewer.