Another option -- when submitting a form, the value for db.file.client 
should be in request.vars.client, so you could do:

custom_store=lambda file, filename, path: store_file(file, filename, path,
    db.client(request.vars.client).client_dir_name if request.vars.client 
else None)

You will also need to fetch the client id in custom_retrieve, though that 
will be trickier because it won't be in request.vars in that case. Instead, 
I would recommend you include the custom directory name within the filename 
created by custom_store -- so custom_store would create a filename like 
table.field.folder.uuid_fragment.encoded_filename.ext. Then your 
custom_retrieve function could simply extract the directory name from the 
filename. In fact, in that case, you don't need an entire custom_retrieve 
function -- instead, you can just implement a 
custom_retrieve_file_properties function (see 
https://code.google.com/p/web2py/source/browse/gluon/dal.py#9355 for what 
that function is supposed to return). That way, when retrieving the file, 
you don't need the client id, and you avoid an unnecessary database query 
to get the directory name (which is already available in the filename).

Anthony

On Monday, April 8, 2013 11:26:09 PM UTC-4, James Burke wrote:
>
> Came up with a workaround.
> def store_file(file, filename=None, path=None):
>  try:
>   client_id = int(request.args[2])
>   client_dir = db(db.client.id == client_id).select(db.client.
> client_dir_name).first().client_dir_name
>  except:
>   client_dir = 'Default'
>  
>  path = "applications/init/uploads/%s" % (client_dir)
>  if not os.path.exists(path):
>  os.makedirs(path)
>  pathfilename = os.path.join(path, filename)
>  dest_file = open(pathfilename, 'wb')
>  try:
>  shutil.copyfileobj(file, dest_file)
>  finally:
>  dest_file.close()
>
>
>  return filename
>
> I'm using a smartgrid so the client id is passed as an argument when I 
> client on the files link.
>
> On Tuesday, April 9, 2013 2:34:35 PM UTC+12, James Burke wrote:
>>
>> Thanks for your swift response.
>>
>> I kind of understand that, but how do you get the value rather than the 
>> field name?
>>
>> db.define_table('file',
>>  Field('client', 'reference client'),
>>  Field('type', requires=IS_IN_SET(['Clipper','Workbench', 'Terramatch',
>> 'Supply']), default='Workbench'),
>>  Field('file', type='upload', 
>>  custom_store=lambda file,filename,path: store_file(file, filename, path,db
>> .file.client._id), 
>>  custom_retrieve=lambda filename, path: retrieve_file(filename, path, db.
>> file.client)),
>>         format='%(file)s')
>>
>> I'm trying to retrieve the clients name and use it to generate the folder.
>>
>> Cheers,
>>
>> -James
>>
>>
>> On Tuesday, April 9, 2013 2:06:54 PM UTC+12, Anthony wrote:
>>>
>>> The fourth argument passed to store_file() is db.table.new_filename, 
>>> which is a DAL Field object. Your code is treating it as a string, and 
>>> "table.new_filename" is the string representation of a Field object. If you 
>>> want to include an actual filename string, then that's what you have to 
>>> pass to the function.
>>>
>>> Anthony
>>>
>>> On Monday, April 8, 2013 9:34:45 PM UTC-4, James Burke wrote:
>>>>
>>>> Hi Anthony,
>>>>
>>>> I've tried the solution you've posted below:
>>>> Field('file', 'upload',
>>>>     custom_store=lambda file, filename, path: store_file(file, filename
>>>> , path, db.table.new_filename),
>>>>     ...)
>>>>
>>>> But when my additional parameter gets sent to store_file it sends 
>>>> 'table.new_filename'
>>>>
>>>> def store_file(file, filename=None, path=None, new_filename=None):
>>>>  path = "applications/init/uploads/%s" % (new_filename)
>>>>  if not os.path.exists(path):
>>>>  os.makedirs(path)
>>>>  pathfilename = os.path.join(path, filename)
>>>>  dest_file = open(pathfilename, 'wb')
>>>>  try:
>>>>  shutil.copyfileobj(file, dest_file)
>>>>  finally:
>>>>  dest_file.close()
>>>>
>>>>
>>>>  return filename
>>>>
>>>> Results in a new folder in uploads called 'table.new_filename'
>>>>
>>>> Cheers 
>>>> -James
>>>>
>>>> On Wednesday, August 8, 2012 11:51:44 PM UTC+12, Anthony wrote:
>>>>>
>>>>> On Wednesday, August 8, 2012 7:09:37 AM UTC-4, Jim Gregory wrote:
>>>>>>
>>>>>> Can custom_store and custom_retrieve take parameters when they are 
>>>>>> called using Field, e.g.:
>>>>>> db.define_table('table',
>>>>>>     Field('file', 'upload', custom_store=store_file(file, 
>>>>>> db.table.new_filename), 
>>>>>> custom_retrieve=retrieve_file(db.table.new_filename))?
>>>>>>     Field('new_filename','string')
>>>>>> )
>>>>>>
>>>>>
>>>>> These attributes have to be callables, so you can't call them 
>>>>> yourself. To pass additional custom arguments to a callable, just turn it 
>>>>> into a lambda that takes the standard arguments and pass the additional 
>>>>> arguments to your function within the lambda:
>>>>>
>>>>> Field('file', 'upload',
>>>>>     custom_store=lambda file, filename, path: store_file(file,filename
>>>>> , path, db.table.new_filename),
>>>>>     ...)
>>>>>
>>>>> When web2py calls the custom_store callable, it will pass three 
>>>>> arguments (file, filename, and path), so your lambda must take three 
>>>>> arguments. Within the lambda, you can then do whatever you want. You can 
>>>>> pass any or all of the standard three arguments to your custom function, 
>>>>> and you can pass additional arguments. In the example above, I passed the 
>>>>> three standard arguments followed by a fourth custom argument, though it 
>>>>> doesn't have to look like that (presumably you will at least want to pass 
>>>>> the file as an argument).
>>>>>
>>>>> custom_retrieve takes two standard arguments, "name" and "path".
>>>>>
>>>>> Anthony
>>>>>
>>>>>

-- 

--- 
You received this message because you are subscribed to the Google Groups 
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to