Using the default download function doesn't work either, it just gives me a
404 Not Found. I don't understand why. It actually allows you to download
and view the spreadsheets?

On Tue, Nov 24, 2015 at 3:29 PM, Anthony <[email protected]> wrote:

> Get rid of your download function and just use the download function that
> comes in the welcome app -- it uses response.download which is designed to
> handle downloading from upload fields automatically. The URL arg, however,
> should be the file name stored in the upload field, not the record ID. (As
> an aside, there would be no need for a StringIO there anyway, as you can
> simply stream the contents of the file directly.)
>
> Anthony
>
>
> On Tuesday, November 24, 2015 at 3:20:56 PM UTC-5, Aeta Gothno wrote:
>>
>> I have added the following into my controller:
>>
>> def download():
>>     file_id = request.args(0)
>>     import cStringIO
>>     import contenttype as c
>>     s=cStringIO.StringIO()
>>
>>     (filename,file) =
>> db.excelform.excel_file.retrieve(db.excelform[file_id].file)
>>     s.write(file.read())
>>     response.headers['Content-Type'] = c.contenttype(filename)
>>     response.headers['Content-Disposition'] = \
>>                 "attachment; filename=%s" % filename
>>     return s.getvalue()
>>
>>
>>
>> def list_files():
>>     excel_file = db(db.excelform.id>0).select(db.excelform.excel_file)
>>     urls = [A('Download', _href=URL(r=request, c='default', f='download',
>> args=[row.id]
>>                  )) for row in excel_file]
>>     return urls
>>
>> However I keep getting the ticket :
>> <type 'exceptions.AttributeError'> 'NoneType' object has no attribute
>> 'file'
>>
>> I am not sure if this is because nothing appears to save in the first
>> place, or if it is because I am using the function wrong.
>>
>> On Tue, Nov 24, 2015 at 1:47 PM, Aeta Gothno <[email protected]>
>> wrote:
>>
>>> Thank you very much for explaining everything to me.
>>>
>>> It makes a lot more sense doing it that way, however I will have to read
>>> up on StringIO since I have not used that before.
>>> I commented out my functions and replaced it with what you have
>>> suggested and there are no errors, however nothing shows up in the uploads
>>> field when I view the database. It is empty, I am not sure if it is because
>>> I am missing something in regards to downloading the file.
>>>
>>> Before I was able to view the excel form being changed in the background
>>> and I would open the new excel file and the user inputs would be in the
>>> correct cells, but now the files are blank. I am confused if it may have
>>> something to do with saving it as a virtual workbook?
>>>
>>> Since there are no errors, I think it at least indicates that it is
>>> opening the excel file and writing to it, I just cannot find where it might
>>> be storing the file afterwards since it shows up empty.
>>>
>>> I also was not aware that I can create functions like so within the
>>> models file, that is very convenient.
>>>
>>> On Tue, Nov 24, 2015 at 12:43 PM, Anthony <[email protected]> wrote:
>>>
>>>> There is no need to store the data in the session and then redirect to
>>>> another action to create the file. Instead, just do it all at once. Also,
>>>> if you want to store the file (safely) and make it easily retrievable, then
>>>> add an upload field to the database table and store it that way. Finally,
>>>> if you want to associated files with their creators, just add a reference
>>>> field to the excelform table to reference the auth_user record of the
>>>> currently logged in user. This can all be simplified as follows:
>>>>
>>>> In a model file:
>>>>
>>>> def create_excel(row):
>>>>     from openpyxl import load_workbook
>>>>     from openpyxl.writer.excel import save_virtual_workbook
>>>>     from cStringIO import StringIO
>>>>     wb = load_workbook(filename=
>>>> '/home/../Documents/web2py/applications/../static/excel.xlsx')
>>>>     sheet_ranges = wb['Sheet1']
>>>>     sheet_ranges['C4'] = row.last_name
>>>>     sheet_ranges['C6'] = row.first_name
>>>>     sheet_ranges['C8'] = row.age
>>>>     sheet_ranges['C10'] = row.location
>>>>     excel_file = StringIO()
>>>>     excel_file.write(save_virtual_workbook(wb))
>>>>     excel_file.seek(0)
>>>>     return db.excelform.excel_file.store(excel_file, 'spreadsheet.xlsx'
>>>> )
>>>>
>>>> db.define_table('excelform',
>>>>     Field('last_name', 'string', requires=IS_NOT_EMPTY()),
>>>>     Field('first_name', 'string', requires=IS_NOT_EMPTY()),
>>>>     Field('age', 'string', requires=IS_NOT_EMPTY()),
>>>>     Field('location', 'string', requires=IS_NOT_EMPTY()),
>>>>     Field('excel_file', 'upload', compute=create_excel),
>>>>     Field('created_by', 'reference auth_user',
>>>>           default=auth.user_id, readable=False, writable=False))
>>>>
>>>> The above adds the excel_file upload field to your model and defines it
>>>> as a computed field. When an insert is made, the create_excel function is
>>>> called. It creates the workbook, but instead of using wb.save() to create
>>>> the file directly, it uses save_virtual_workbook to convert the workbook to
>>>> a string. It then writes the string to a StringIO object, which is
>>>> ultimately passed to the .store() method of the upload field. The .store()
>>>> method creates the file and returns the filename that web2py created for
>>>> it, which is ultimately stored in the upload field itself. The second
>>>> argument to .store() is the filename you will see when you download the
>>>> file (but no the filename used to actually store the file on the
>>>> filesystem).
>>>>
>>>> The created_by field is a reference to auth_user, with the default set
>>>> to the ID of the current user (it is not readable or writable, so will not
>>>> appear in the form).
>>>>
>>>> Then, in the controller:
>>>>
>>>> @auth.requires_login()
>>>> def excelform():
>>>>     record = db.excelform(request.args(0))
>>>>     form = SQLFORM(db.excelform, record,
>>>>                    message_onsuccess='Thanks! The form has been
>>>> submitted.',
>>>>                    message_onfailure='Please correct the error(s).').
>>>> process()
>>>>     return dict(form=form)
>>>>
>>>> The controller is now quite simple -- it just creates and processes the
>>>> form -- the rest of the logic is handled in the model. Note, assuming being
>>>> a registered user is required, you should use the @auth.requires_login()
>>>> decorator here.
>>>>
>>>> If you want to show only the files of the current user, you can do:
>>>>
>>>>     grid = SQLFORM.grid(db.excelform.created_by == auth.user_id)
>>>>
>>>> Anthony
>>>>
>>>> --
>>>> Resources:
>>>> - http://web2py.com
>>>> - http://web2py.com/book (Documentation)
>>>> - http://github.com/web2py/web2py (Source code)
>>>> - https://code.google.com/p/web2py/issues/list (Report Issues)
>>>> ---
>>>> You received this message because you are subscribed to a topic in the
>>>> Google Groups "web2py-users" group.
>>>> To unsubscribe from this topic, visit
>>>> https://groups.google.com/d/topic/web2py/B4H1Q6jV9S4/unsubscribe.
>>>> To unsubscribe from this group and all its topics, send an email to
>>>> [email protected].
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>>
>>>
>> --
> Resources:
> - http://web2py.com
> - http://web2py.com/book (Documentation)
> - http://github.com/web2py/web2py (Source code)
> - https://code.google.com/p/web2py/issues/list (Report Issues)
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "web2py-users" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/web2py/B4H1Q6jV9S4/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> [email protected].
> For more options, visit https://groups.google.com/d/optout.
>

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
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/d/optout.

Reply via email to