Reputation: 2298
I have a repeatable form field:
<div class="repeat">
<input type="file" name="files[==row-count-placeholder==]" />
</div>
that will (using jQuery) for example result in
<div class="repeat">
<input type="file" name="files[0]" />
<input type="file" name="files[1]" />
<input type="file" name="files[2]" />
<!-- and so on -->
</div>
according to how many files want to be uploaded by the user. The forms method is post
and enctype is multipart/form-data
.
Using cherrypy as my server and voluptuous validation library I would like to save the uploaded files:
import voluptuous
def save_uploaded_file(file, path)
#save file on server...
def validate_files(files):
for file in files:
save_uploaded_file(file, cherrypy.request.config['static_dir'])
@cherrypy.expose
def index(self, **kwargs):
schema = Schema({
'files' : validate_files
}, required = True, extra = True)
kwargs = schema(kwargs)
Therefore I would actually need a post header that contains information for all the files (best would be something like a list of the files) according to one key called files
, but all I get is multiple keys such as files[0]
, files[1]
and so on...
How do I approach this? Do I somehow have to manually create an array that contains all the files
information or is there a more common or practical way to do it?
Solution (following saaj's suggestion):
schema_dict = {
'name' : All(Length(min=3, msg="Can't believe that there is a name less than 3 characters...")),
# ...
}
# validate files
isPart = lambda v: isinstance(v, cherrypy._cpreqbody.Part)
files1 = [a for a in kwargs.values() if isPart(a)]
files2 = [a for a in cherrypy.request.params.values() if isPart(a)]
assert files1 == files2
for file in files1:
# for each file add dict entry and route to validation function
schema_dict.update({file.name : validate_file})
schema = volu.Schema(schema_dict, required = True, extra = True)
Like this a Schema
can obviously contain many other fields. Submitted files are being added generically to any Schema
. Cool!
Upvotes: 3
Views: 378
Reputation: 25234
Just take file parts from request (if your form doesn't contain other types of parts you can take request's params as is).
@cherrypy.expose
def index(self, **kwargs):
isPart = lambda v: isinstance(v, cherrypy._cpreqbody.Part)
files1 = [a for a in kwargs.values() if isPart(a)]
files2 = [a for a in cherrypy.request.params.values() if isPart(a)]
assert files1 == files2
print(files1) # pass it where you want to
Related CherryPy questions: upload performance, asynchronous upload.
Upvotes: 1