[Mpuls-commits] r1911 - in wasko/branches/2.0: . mpulsweb/controllers mpulsweb/lib mpulsweb/model mpulsweb/templates/documents

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Mon Mar 8 16:22:34 CET 2010


Author: torsten
Date: 2010-03-08 16:22:31 +0100 (Mon, 08 Mar 2010)
New Revision: 1911

Modified:
   wasko/branches/2.0/ChangeLog
   wasko/branches/2.0/mpulsweb/controllers/casedocument.py
   wasko/branches/2.0/mpulsweb/controllers/document.py
   wasko/branches/2.0/mpulsweb/lib/validators.py
   wasko/branches/2.0/mpulsweb/model/document.py
   wasko/branches/2.0/mpulsweb/templates/documents/case_new.mako
   wasko/branches/2.0/mpulsweb/templates/documents/global_upload.mako
Log:
Fixed wald issue 1288


Modified: wasko/branches/2.0/ChangeLog
===================================================================
--- wasko/branches/2.0/ChangeLog	2010-03-08 12:04:18 UTC (rev 1910)
+++ wasko/branches/2.0/ChangeLog	2010-03-08 15:22:31 UTC (rev 1911)
@@ -11,8 +11,20 @@
 	* waskaweb/lib/validators.py:Do not import StringTooLong validator
 	* mpulsweb/lib/validators.py (StringTooLong): Deleted. Not used
 	  anymore.
- 
 
+	Fileuploads
+
+	* mpulsweb/model/document.py,
+	  mpulsweb/controllers/casedocument.py,
+	  mpulsweb/controllers/document.py,
+	  mpulsweb/lib/validators.py,
+	  mpulsweb/templates/documents/case_new.mako,
+	  mpulsweb/templates/documents/global_upload.mako: Changed upload
+	  logic. Now the user can give an optional name for documents. This
+	  enables saving files under an alternativ name. Further the user can
+	  select if he wants to overwrite any existing files with the same
+	  name. For that some new validator logic was written.
+
 2010-03-05  Torsten Irländer <torsten.irlaender at intevation.de>
 
 	* mpulsweb/lib/validators.py (LoginCheck.validate_python): Fixed mpuls

Modified: wasko/branches/2.0/mpulsweb/controllers/casedocument.py
===================================================================
--- wasko/branches/2.0/mpulsweb/controllers/casedocument.py	2010-03-08 12:04:18 UTC (rev 1910)
+++ wasko/branches/2.0/mpulsweb/controllers/casedocument.py	2010-03-08 15:22:31 UTC (rev 1911)
@@ -1,5 +1,6 @@
 # -*- coding: utf-8 -*-
 import logging
+import formencode
 
 import paste
 
@@ -7,6 +8,7 @@
 from pylons.controllers.util import redirect_to
 
 from mpulsweb.lib.base import BaseController, render
+from mpulsweb.lib.validators import UploadCaseDocumentForm 
 from mpulsweb.lib.security import checkRole
 import mpulsweb.lib.helpers as h
 
@@ -50,36 +52,30 @@
 
     @checkRole('cm_ka')
     def newAction(self):
+        validator = UploadCaseDocumentForm()
         try:
-            case = int(request.POST['case'])
-        except:
-            redirect_to(controller="casedocument", action="index")
-
-        try:
+            result = validator.to_python(request.params)
             doc = Document()
-            myfile = None
-            try:
-                myfile = request.POST.get('file')
-                if not myfile is None:
-                    doc.create(myfile.filename, myfile.file, case)
-                    c.success_for = SET_ATTACHMENT_SUCCESS_HEADER
-                    c.success_text = SET_ATTACHMENT_SUCCESS_TEXT
-                    c.url_ok = h.url_for(controller="/casedocument",
-                                         action="index", id=case)
-                    return render('/documents/dialogs/success_attachment.mako')
-            finally:
-                if not myfile is None:
-                    try:
-                        myfile.file.close()
-                    except:
-                        pass
-        except Exception, e:
-            log.exception(e)
-            c.failed_for = SET_ATTACHMENT_FAILED_HEADER
-            c.failed_text = SET_ATTACHMENT_FAILED_TEXT
+            filename = result['file']['filename']
+            content = result['file']['content']
+            case = result['case']
+            if result['name']:
+                filename = result['name']
+            doc.create(filename, content, case)
+            c.dialog_title = SET_ATTACHMENT_SUCCESS_HEADER
+            c.dialog_text = SET_ATTACHMENT_SUCCESS_TEXT
             c.url_ok = h.url_for(controller="/casedocument",
-                                 action="new", id=case)
-            return render('/documents/dialogs/failed_attachment.mako')
+                                 action="index", id=case)
+            return render('/documents/dialogs/success_attachment.mako')
+        except formencode.Invalid, error:
+            c.form_result = error.value
+            c.form_errors = error.error_dict or {}
+            log.debug(c.form_result)
+            form = render('/documents/case_new.mako')
+            return formencode.htmlfill.render(unicode(form, 'utf-8'),
+                                              defaults=c.form_result,
+                                              auto_insert_errors=False,
+                                              errors=c.form_errors)
 
     @checkRole(('admin_ka', 'cm_ka'))
     def show(self, id):

Modified: wasko/branches/2.0/mpulsweb/controllers/document.py
===================================================================
--- wasko/branches/2.0/mpulsweb/controllers/document.py	2010-03-08 12:04:18 UTC (rev 1910)
+++ wasko/branches/2.0/mpulsweb/controllers/document.py	2010-03-08 15:22:31 UTC (rev 1911)
@@ -28,12 +28,14 @@
 # Sascha L. Teichmann <teichmann at intevation.de>
 #
 import logging
+import formencode
 
 import paste
 from pylons import config
 
 from mpulsweb.lib.base import BaseController, c, h, redirect_to, render, request
 from mpulsweb.lib.security import checkRole
+from mpulsweb.lib.validators import UploadGlobalDocumentForm 
 from mpulsweb.model.document import Document, listDocuments, deleteDocument
 
 SET_DOCUMENT_SUCCESS_HEADER = u"""Dokument hinzugefügt!"""
@@ -91,30 +93,29 @@
 
     @checkRole('admin_ka')
     def globalUploadAction(self):
+        validator = UploadGlobalDocumentForm()
         try:
+            result = validator.to_python(request.params)
             doc = Document()
-            myfile = None
-            try:
-                myfile = request.POST.get('file')
-                if not myfile is None:
-                    doc.create(myfile.filename, myfile.file)
-                    c.dialog_title = SET_DOCUMENT_SUCCESS_HEADER
-                    c.dialog_text = SET_DOCUMENT_SUCCESS_TEXT
-                    c.url_ok = h.url_for(controller="document",
-                                         action="globalOverview")
-                    return render('/documents/dialogs/success_documents.mako')
-            finally:
-                if not myfile is None:
-                    try:
-                        myfile.file.close()
-                    except Exception, e:
-                        log.exception(e)
-        except Exception, e:
-            log.exception(e)
-            c.dialog_title = SET_DOCUMENT_FAILED_HEADER
-            c.dialog_text = SET_DOCUMENT_FAILED_TEXT
-            c.url_ok = h.url_for(controller="document", action="globalUpload")
-            return render('/documents/dialogs/failed_document.mako')
+            filename = result['file']['filename']
+            content = result['file']['content']
+            if result['name']:
+                filename = result['name']
+            doc.create(filename, content)
+            c.dialog_title = SET_DOCUMENT_SUCCESS_HEADER
+            c.dialog_text = SET_DOCUMENT_SUCCESS_TEXT
+            c.url_ok = h.url_for(controller="document",
+                                 action="globalOverview")
+            return render('/documents/dialogs/success_documents.mako')
+        except formencode.Invalid, error:
+            c.form_result = error.value
+            c.form_errors = error.error_dict or {}
+            log.debug(c.form_result)
+            form = render('/documents/global_upload.mako')
+            return formencode.htmlfill.render(unicode(form, 'utf-8'),
+                                              defaults=c.form_result,
+                                              auto_insert_errors=False,
+                                              errors=c.form_errors)
 
     @checkRole(('admin_ka', 'cm_ka'))
     def globalShow(self, id):

Modified: wasko/branches/2.0/mpulsweb/lib/validators.py
===================================================================
--- wasko/branches/2.0/mpulsweb/lib/validators.py	2010-03-08 12:04:18 UTC (rev 1910)
+++ wasko/branches/2.0/mpulsweb/lib/validators.py	2010-03-08 15:22:31 UTC (rev 1911)
@@ -2,12 +2,14 @@
 
 import re
 import logging
+import cgi
 import datetime
 
 import formencode
 from formencode import ForEach, All
 from formencode.validators import Bool, Int, String, FieldsMatch, StringBoolean, \
-     DateConverter, DateValidator, TimeConverter, FormValidator, MaxLength
+     DateConverter, DateValidator, TimeConverter, FormValidator, MaxLength, \
+     FileUploadKeeper, FieldStorageUploadConverter
 
 from pylons import session
 from pylons.i18n import _
@@ -34,6 +36,107 @@
     allow_extra_fields = True
     filter_extra_fields = False
 
+class FileNotEmptyCheck(formencode.validators.FancyValidator):
+
+    '''Checks if the filename-field of the  provided file-dict ist empty. This
+    means that the user has not provided a file. Further check if the file is largger than the max allowed filesize'''
+
+    max_size = 10000000 #10MB = 10000000 bytes
+
+    messages = {
+        'nofile': (u'Bitte geben Sie eine Datei zum Hochladen an.'),
+        'toobig': (u'Die Datei ist größer als die maximal zulässige Größe von 10MB.')
+        }
+
+    def _to_python(self, value, state=None):
+        if not value.get('filename'):
+            raise formencode.Invalid(self.message("nofile", state),
+                                     value, state)
+        if len(value.get('content')) > self.max_size :
+            raise formencode.Invalid(self.message("toobig", state),
+                                     value, state)
+        return value
+
+class FileExistsChecker(FormValidator):
+    """
+        Checks if a given file (or filename) already exists in the database. If
+        so raise an exception if the user did not want to overwrite it.
+    """
+
+    casedoc_sql = "SELECT id FROM ka_fall_dokumente_tbl_view WHERE name = '%(filename)s'" 
+    globaldoc_sql = "SELECT id FROM ka_global_dokumente_tbl_view WHERE name = '%(filename)s'" 
+    field_names = None
+    validate_partial_form = True
+    __unpackargs__ = ('*', 'field_names')
+
+    messages = {
+        'fileexists': _("Es existiert bereits eine Datei mit dem Namen"),
+        'notDict': _("Fields should be a dictionary"),
+        }
+
+    def __init__(self, *args, **kw):
+        super(FormValidator, self).__init__(*args, **kw)
+        if len(self.field_names) < 2:
+            raise TypeError("FieldsMatch() requires at least two field names")
+
+    def validate_partial(self, field_dict, state):
+        for name in self.field_names:
+            if not field_dict.has_key(name):
+                return
+        self.validate_python(field_dict, state)
+
+    def validate_python(self, field_dict, state):
+        try:
+            ref = field_dict[self.field_names[0]]
+        except TypeError:
+            # Generally because field_dict isn't a dict
+            raise Invalid(self.message('notDict', state), field_dict, state)
+        except KeyError:
+            ref = ''
+
+        file = field_dict[self.field_names[0]]
+        # if user gives a userdefined name for the file take ths to check if
+        # the file is already existent. Else take filename from file
+        name = field_dict[self.field_names[1]]
+        if not name:
+            name = file.get('filename')
+            field_dict[self.field_names[1]] = name
+
+        ow = field_dict[self.field_names[2]]
+        case = field_dict.get(self.field_names[3])
+        if case:
+            sql = self.casedoc_sql
+        else:
+            sql = self.globaldoc_sql
+        errors = {}
+
+        # Only check if there is a file with name in DB, if teh user do not
+        # what do overwrite the files with the same name.
+        if not ow:
+            conn, cur = None, None
+            try:
+                conn = db.getConnection()
+                cur = conn.cursor()
+                fields = {'filename': name}
+                cur.execute(sql % fields)
+                result = cur.fetchone()
+                if result:
+                    errors['name'] = self.message('fileexists', state)
+            except Exception, e:
+                log.exception(e)
+                raise
+            finally:
+                db.recycleConnection(conn, cur)
+
+        if errors:
+            error_list = errors.items()
+            error_list.sort()
+            error_message = '<br>\n'.join(
+                ['%s: %s' % (name, value) for name, value in error_list])
+            raise formencode.Invalid(error_message,
+                          field_dict, state,
+                          error_dict=errors)
+
 class DateOrder(FormValidator):
 
     """
@@ -342,7 +445,22 @@
 
     _from_python = _to_python
 
+class UploadGlobalDocumentForm(BaseFormValidator):
+    pre_validators = [formencode.variabledecode.NestedVariables()]
+    file = All(FileNotEmptyCheck(not_empty=True), FileUploadKeeper())
+    name = String()
+    overwrite = Bool(if_missing=False)
+    chained_validators = [FileExistsChecker('file', 'name', 'overwrite', 'case')]
 
+class UploadCaseDocumentForm(BaseFormValidator):
+    pre_validators = [formencode.variabledecode.NestedVariables()]
+    file = All(FileNotEmptyCheck(not_empty=True), FileUploadKeeper())
+    name = String()
+    overwrite = Bool(if_missing=False)
+    case = Int(not_empty=True)
+    chained_validators = [FileExistsChecker('file', 'name', 'overwrite', 'case')]
+
+
 class EditSettingsForm(BaseFormValidator):
 
     anon_transfer = formencode.validators.String(if_missing='off')

Modified: wasko/branches/2.0/mpulsweb/model/document.py
===================================================================
--- wasko/branches/2.0/mpulsweb/model/document.py	2010-03-08 12:04:18 UTC (rev 1910)
+++ wasko/branches/2.0/mpulsweb/model/document.py	2010-03-08 15:22:31 UTC (rev 1911)
@@ -186,25 +186,9 @@
             case = int(case)
             self.case = case
 
-        out = StringIO.StringIO()
-        total_size = 0
-        while True:
-            b = src.read(BLOCK_SIZE)
-            l = len(b)
-            if l == 0:
-                break
-            total_size += l
-            if total_size > MAX_SIZE:
-                raise DocumentException(
-                    u"Datei ist zu groß. Maximal %sMB sind erlaubt."
-                    % h.format_number(MAX_SIZE/float(1024*1024)))
-            out.write(b)
-        bytes = out.getvalue()
-        out.close()
-        out = None
+        bytes = src 
+        self.size = len(bytes) #total_size
 
-        self.size = total_size
-
         has_commited = False
         con, cur = None, None
         try:
@@ -222,7 +206,7 @@
                 raise DocumentException("Konnte neues Dokument nicht anlegen.")
 
             id = row[0]
-            fields = {'bytes': dbapi.Binary(bytes), 'size': total_size,
+            fields = {'bytes': dbapi.Binary(bytes), 'size': self.size,
                       'name': name, 'mime': mime, 'id': id}
 
             if case is None:

Modified: wasko/branches/2.0/mpulsweb/templates/documents/case_new.mako
===================================================================
--- wasko/branches/2.0/mpulsweb/templates/documents/case_new.mako	2010-03-08 12:04:18 UTC (rev 1910)
+++ wasko/branches/2.0/mpulsweb/templates/documents/case_new.mako	2010-03-08 15:22:31 UTC (rev 1911)
@@ -35,26 +35,68 @@
     </div>
   </div>
 </div>
-
-<div id="document">
-  <div id="waska_form" class="import_box">
-    <p class="import_p">
-      Die Größe einer Anlage darf nicht 10MB überschreiten. Bereits bestehende
-      Dateien mit gleichem Namen werden überschrieben!
-    </p>
-    <div class="import_box_dialog">
-      ${h.form(h.url_for(controller="casedocument", action='newAction'), 
-          multipart=True)}
-      <label class="import_label" for="file">
-        <strong class="import_number"> 1. </strong>${_('att_form_upload_label_add')}
-      </label>
-      ${h.file('file')}<br>
-      <label class="import_label" for="">
-        <strong class="import_number">2. </strong>${_('att_form_upload_label_up')}
-      </label>
-      ${h.submit("upload", _('doc_form_upload_submit'))}
-      ${h.hidden('case', value=session.get('case').id)}
-      ${h.end_form()}
-    </div>
-  </div>
+<p class="import_p">
+  Die Größe eines Dokuments darf nicht 10MB überschreiten.</p>
+${h.form(h.url_for(controller="casedocument", action='newAction'), 
+  multipart=True)}
+<div class="widget container">
+  <table class="form">
+    <tr>
+      <td class="label">
+        <label for="name">
+          ${_('File')}
+        </label>
+      </td>
+      <td class="">
+        <input type="file" name="file.upload" id="file">
+        <input type="hidden" name="file.static">
+      </td>
+      <td class=""><span class="error"><form:error name="file"></span></td>
+    </tr>
+    <tr>
+      <td class="label">
+        <label for="name">${_('Filename')}</label></td>
+      <td class="">
+        <input type="text" name="name" id="name"><br>
+      </td>
+      <td class=""><span class="error"><form:error name="name"></span></td>
+    </tr>
+    <tr>
+      <td class="label">
+      <td class="">
+        <p class="note">Sie können optional einen alternativen Namen für
+        die Datei angeben, um so mehrere Versionen eines Dokuments
+        hinterlegen zu können. Wenn Sie keinen Namen angeben, so wird der
+        Dateiname der Datei verwendet, die Sie hochladen.  </p>
+      </td>
+      <td class=""></td>
+    </tr>
+    <tr>
+      <td class="label">
+          ${_('Overwrite')}
+      </td>
+      <td class="">
+        <input type="checkbox" name="overwrite" value="1" id="overwrite">
+          <label for="overwrite">
+            ${_('Overwrite files with same name')}
+          </label>
+      </td>
+      <td class=""><span class="error"><form:error name="overwrite"></span></td>
+    </tr>
+    <tr>
+      <td class="label">
+      <td class="">
+        <p class="note">Beachten Sie, dass Sie den Haken bei "Überschreiben" setzen müssen, wenn Sie Daten gleichen Namens überschreiben wollen.</p>
+      </td>
+      <td class=""></td>
+    </tr>
+    <tr>
+      <td class=""></td>
+      <td colspan="2">
+        ${h.hidden('case', value=session.get('case').id)}
+        ${h.submit('upload', _('doc_form_upload_submit'))}
+      </td>
+    </tr>
+  </table>
 </div>
+${h.end_form()}

Modified: wasko/branches/2.0/mpulsweb/templates/documents/global_upload.mako
===================================================================
--- wasko/branches/2.0/mpulsweb/templates/documents/global_upload.mako	2010-03-08 12:04:18 UTC (rev 1910)
+++ wasko/branches/2.0/mpulsweb/templates/documents/global_upload.mako	2010-03-08 15:22:31 UTC (rev 1911)
@@ -23,24 +23,67 @@
   </div>
 </div>
 
-<div id="document">
-  <div id="waska_form" class="import_box">
-    <p class="import_p">
-      Die Größe eines Dokuments darf nicht 10MB überschreiten. Bereits bestehende
-      Dateien mit gleichem Namen werden überschrieben!
-    </p>
-    <div class="import_box_dialog">
-      ${h.form(h.url_for(controller="document", action='globalUploadAction'), 
-        multipart=True)}
-      <label class="import_label" for="file">
-        <strong class="import_number">1. </strong>${_('doc_form_upload_label_file')}
-      </label>
-      ${h.file('file')}<br>
-      <label class="import_label" for="">
-        <strong class="import_number">2.</strong> Dokument hinzufügen:
-      </label>
-      ${h.submit('upload', _('doc_form_upload_submit'))}
-      ${h.end_form()}
-    </div>
-  </div>
+<p class="import_p">
+  Die Größe eines Dokuments darf nicht 10MB überschreiten.</p>
+${h.form(h.url_for(controller="document", action='globalUploadAction'), 
+  multipart=True)}
+<div class="widget container">
+  <table class="form">
+    <tr>
+      <td class="label">
+        <label for="name">
+          ${_('File')}
+        </label>
+      </td>
+      <td class="">
+        <input type="file" name="file.upload" id="file">
+        <input type="hidden" name="file.static">
+      </td>
+      <td class=""><span class="error"><form:error name="file"></span></td>
+    </tr>
+    <tr>
+      <td class="label">
+        <label for="name">${_('Filename')}</label></td>
+      <td class="">
+        <input type="text" name="name" id="name"><br>
+      </td>
+      <td class=""><span class="error"><form:error name="name"></span></td>
+    </tr>
+    <tr>
+      <td class="label">
+      <td class="">
+        <p class="note">Sie können optional einen alternativen Namen für
+        die Datei angeben, um so mehrere Versionen eines Dokuments
+        hinterlegen zu können. Wenn Sie keinen Namen angeben, so wird der
+        Dateiname der Datei verwendet, die Sie hochladen.  </p>
+      </td>
+      <td class=""></td>
+    </tr>
+    <tr>
+      <td class="label">
+          ${_('Overwrite')}
+      </td>
+      <td class="">
+        <input type="checkbox" name="overwrite" value="1" id="overwrite">
+          <label for="overwrite">
+            ${_('Overwrite files with same name')}
+          </label>
+      </td>
+      <td class=""><span class="error"><form:error name="overwrite"></span></td>
+    </tr>
+    <tr>
+      <td class="label">
+      <td class="">
+        <p class="note">Beachten Sie, dass Sie den Haken bei "Überschreiben" setzen müssen, wenn Sie Daten gleichen Namens überschreiben wollen.</p>
+      </td>
+      <td class=""></td>
+    </tr>
+    <tr>
+      <td class=""></td>
+      <td colspan="2">
+        ${h.submit('upload', _('doc_form_upload_submit'))}
+      </td>
+    </tr>
+  </table>
 </div>
+${h.end_form()}



More information about the Mpuls-commits mailing list