colander

Colander deform file upload widget


I want to upload a single file with the following colander schema:

import colander
import deform
from deform.interfaces import FileUploadTempStore 

@view_config(route_name='upload',
             renderer='templates/upload.pt',
             permission='view')
def upload(self):
    tmpstore = FileUploadTempStore()
    class Schema(colander.Schema):
        name = colander.SchemaNode(
            deform.FileData(),
            widget=deform.widget.FileUploadWidget(tmpstore),
            title='Upload'
        )
    def on_validated(request, captured):
        pass
    schema = Schema()
    form = deform.Form(schema, buttons=('upload',), formid='form')
    html = []
    captured = None
    if 'upload' in self.request.POST:
        try:
            controls = self.request.POST.items()
            captured = form.validate(controls)
            response = on_validated(self.request, captured)
            if response is not None:
                return response
        except deform.ValidationFailure as e:
            html.append(e.render())
    else:
        html.append(form.render())
    html = ''.join(html)
    return {
        'form': html,
    }

The view works fine, I can browse and select a file. However, when I press the "upload" button, I get the error: TypeError: 'NoneType' object does not support item assignment

The controls is defined, but the form.validate() is the problem. It refers to deform/widget.py line 1674:

self.tmpstore[uid]['preview_url'] = preview_url

Solution

  • Fixed by defining the tmpstore differently (from deformdemo/init.py):

        class MemoryTmpStore(dict):
            """ Instances of this class implement the
            :class:`deform.interfaces.FileUploadTempStore` interface"""
    
            def preview_url(self, uid):
                return None
    
        tmpstore = MemoryTmpStore()