You are using SQLFORM.factory to handle the upload, but the table and field
names used there do not match the table or field names where the records
are actually stored, so response.download() cannot find the appropriate
table or field. By default, SQLFORM.factory uses "no_table" as the dummy
table name, and your code uses "image" as the field name. So, your image
files will end up with names that start with "no_table.image". As a result,
response.download(request, db) will look for a db.no_table table with an
"image" field, but obviously won't find it. Instead, your image filenames
are actually stored in db.auth_user.t_image, so you need to make sure the
filenames get generated with names starting with "auth_user.t_image".
Also, if you specify a custom uploadfolder, you'll need to make sure that
the db.auth_user.t_image field has that uploadfolder specified as well,
because response.download() checks the actual db field to determine the
uploadfolder. The easiest approach might be to define the field once and
reference both in the appended auth_user fields and in SQLFORM.factory.
Finally, you can specify the name of the dummy table used by
SQLFORM.factory by passing a "table_name" argument.
So, maybe something like this:
image_field = Field('t_image', 'upload', ..., uploadfolder=[your upload
folder])
auth.settings.extra_fields['auth_user'] = [..., image_field, ...]
...
tform = SQLFORM.factory(..., image_field, ..., table_name='auth.user')
Actually, you should probably do that with all the fields in
SQLFORM.factory -- define them all once and use them in db.auth_user and to
make the form. As it is, the field definitions in db.auth_user don't even
have the correct field types defined. You could first add all the fields to
db.auth_user, and then do something like this:
tform = SQLFORM.factory(*[f for f in db.auth_user if f.name.startswith('t_'
)], ...)
That will include all the fields from db.auth_user that start with "t_".
Finally, note that there will not be any errors in the form until you
process it, so your condition that checks for errors will never find any.
First call, form.process(), and then check for errors.
Anthony
On Thursday, December 6, 2012 8:51:02 AM UTC-5, Daniele wrote:
>
> Ok here's my code:
>
> in db.py
>
> from gluon.tools import Auth, Crud, Service, PluginManager, prettydate
>
>
> auth = Auth(db)
> auth.settings.extra_fields['auth_user']= [
>
>
> # t denote tutor fields, s denote student fields.
> Field <http://127.0.0.1:8000/examples/global/vars/Field>('t_image'),
>
>
> Field <http://127.0.0.1:8000/examples/global/vars/Field>('t_location'),
>
>
> Field <http://127.0.0.1:8000/examples/global/vars/Field>('t_subjects'),
>
>
> Field
> <http://127.0.0.1:8000/examples/global/vars/Field>('t_qualifications'),
>
>
> Field <http://127.0.0.1:8000/examples/global/vars/Field>('t_biography'),
>
>
> Field <http://127.0.0.1:8000/examples/global/vars/Field>('t_hourly_rate'),
>
>
> Field <http://127.0.0.1:8000/examples/global/vars/Field>('t_modified_on'),
>
>
> Field <http://127.0.0.1:8000/examples/global/vars/Field>('s_location')]
>
>
>
> in my controller:
>
> @auth.requires_login()
> def edit_profile():
> response <http://127.0.0.1:8000/examples/global/vars/response>.subtitle =
> T <http://127.0.0.1:8000/examples/global/vars/T>("Edit Profile")
>
>
> # Tutor form
> tform = SQLFORM
> <http://127.0.0.1:8000/examples/global/vars/SQLFORM>.factory(
>
>
> Field <http://127.0.0.1:8000/examples/global/vars/Field>('is_tutor',
> 'boolean'),
>
>
> Field <http://127.0.0.1:8000/examples/global/vars/Field>('image',
> 'upload', requires=IS_EMPTY_OR
> <http://127.0.0.1:8000/examples/global/vars/IS_EMPTY_OR>(IS_IMAGE
> <http://127.0.0.1:8000/examples/global/vars/IS_IMAGE>(extensions=('jpeg',
> 'jpg', 'png', 'gif')))),
>
>
> Field <http://127.0.0.1:8000/examples/global/vars/Field>('location',
> 'list:string', requires=IS_NOT_EMPTY
> <http://127.0.0.1:8000/examples/global/vars/IS_NOT_EMPTY>()),
>
>
> Field <http://127.0.0.1:8000/examples/global/vars/Field>('subjects',
> 'list:string', requires=IS_NOT_EMPTY
> <http://127.0.0.1:8000/examples/global/vars/IS_NOT_EMPTY>()),
>
>
> Field
> <http://127.0.0.1:8000/examples/global/vars/Field>('qualifications',
> 'list:string', requires=IS_NOT_EMPTY
> <http://127.0.0.1:8000/examples/global/vars/IS_NOT_EMPTY>()),
>
>
> Field <http://127.0.0.1:8000/examples/global/vars/Field>('biography',
> 'text'),
>
>
> Field
> <http://127.0.0.1:8000/examples/global/vars/Field>('hourly_rate',
> 'decimal(7,2)', requires=IS_NOT_EMPTY
> <http://127.0.0.1:8000/examples/global/vars/IS_NOT_EMPTY>()),
>
>
> Field
> <http://127.0.0.1:8000/examples/global/vars/Field>('modified_on', 'datetime',
> requires=IS_DATETIME
> <http://127.0.0.1:8000/examples/global/vars/IS_DATETIME>(), writable=False,
> readable=False, default=request
> <http://127.0.0.1:8000/examples/global/vars/request>.utcnow),
>
>
> upload=URL
> <http://127.0.0.1:8000/examples/global/vars/URL>('download'),
>
>
> table_name='tutor')
>
> # Student form
>
>
> sform = SQLFORM
> <http://127.0.0.1:8000/examples/global/vars/SQLFORM>.factory(
>
>
> Field
> <http://127.0.0.1:8000/examples/global/vars/Field>('is_student', 'boolean'),
>
>
> Field <http://127.0.0.1:8000/examples/global/vars/Field>('location',
> 'list:string', requires=IS_NOT_EMPTY
> <http://127.0.0.1:8000/examples/global/vars/IS_NOT_EMPTY>()),
>
>
> table_name='student')
>
> tform['_class'] = "form-horizontal"
>
>
> sform['_class'] = "form-horizontal"
>
>
> tform.custom.submit['_class'] = "btn btn-success"
>
>
> sform.custom.submit['_class'] = "btn btn-success"
>
>
> tform.custom.begin = XML
> <http://127.0.0.1:8000/examples/global/vars/XML>("<%s %s>" % (tform.tag,
> tform._xml()[0]))
>
>
> sform.custom.begin = XML
> <http://127.0.0.1:8000/examples/global/vars/XML>("<%s %s>" % (sform.tag,
> sform._xml()[0]))
>
>
>
> if tform.errors or sform.errors:
>
>
> response <http://127.0.0.1:8000/examples/global/vars/response>.flash
> = T <http://127.0.0.1:8000/examples/global/vars/T>('There was an error with
> your submission')
>
>
> else:
> if tform.process().accepted:
>
>
> if tform.vars.is_tutor:
> if not auth.has_membership('Tutors'):
>
>
> auth.add_membership('Tutors')
> db(db.auth_user.id == auth.user_id).update(
>
>
> t_image = tform.vars.image,
> t_location = tform.vars.location,
>
>
> t_subjects = tform.vars.subjects,
> t_qualifications = tform.vars.qualifications,
>
>
> t_biography = tform.vars.biography,
> t_hourly_rate = tform.vars.hourly_rate,
>
>
> t_modified_on = tform.vars.modified_on
> )
>
>
> else:
> if auth.has_membership('Tutors'):
>
>
> auth.del_membership('Tutors')
> #db.auth_user.delete() delete the records
>
>
> response
> <http://127.0.0.1:8000/examples/global/vars/response>.flash = T
> <http://127.0.0.1:8000/examples/global/vars/T>('Profile updated!')
>
>
>
> if sform.process().accepted:
>
>
> if sform.vars.is_student:
> if not auth.has_membership('Students'):
>
>
> auth.add_membership('Students')
>
>
> db(db.auth_user.id == auth.user_id).update(
>
>
> s_location = sform.vars.location
> )
>
>
> else:
> if auth.has_membership('Students'):
>
>
> auth.del_membership('Students')
>
>
> response
> <http://127.0.0.1:8000/examples/global/vars/response>.flash = T
> <http://127.0.0.1:8000/examples/global/vars/T>('Profile updated!')
>
>
> return dict(tform=tform, sform=sform)
>
>
>
>
> On Thu, Dec 6, 2012 at 1:48 PM, Anthony <[email protected]
> <javascript:>>wrote:
>
>> You mention using SQLFORM.factory -- do you actually store the record in
>> a db table, does that db table name match the name at the beginning of the
>> filename, and is the 'image' field definition in the model for that table
>> the same as the field definition you're using in SQLFORM.factory? It might
>> help if you show all of the relevant model and controller code.
>>
>> Anthony
>>
>>
>> On Thursday, December 6, 2012 8:33:10 AM UTC-5, Daniele wrote:
>>
>>> I noticed that I am missing upload=URL('download') in my
>>> SQLFORM.factory, so I added that in there but it's still not working.
>>>
>>> I double checked the image name and you were right, I don't know how I
>>> must have mistakenly deleted that part but it was indeed
>>> "[table_name].[field_name].[**rand_string]"
>>>
>>> I can't think of why else this is not working...I am following the
>>> web2py book verbatim...
>>>
>>>
>>> On Thu, Dec 6, 2012 at 3:06 AM, Anthony <[email protected]> wrote:
>>>
>>>>
>>>> Hmm for some reason it's not working for me. I took a look at the
>>>>> source code and this is the HTML that is being generated:
>>>>>
>>>>> <img
>>>>> src="/download/image.**a6e29a6f3**6771685.**e58699e79c9f2e4a5047.**JPG" />
>>>>>
>>>>>
>>>>> And this is what I have in my view that is generating that code:
>>>>>
>>>>> {{=IMG(_src=URL('default', 'download', args=row.image))}}
>>>>>
>>>>> so it seems to be taking the 'download' directory and looking for the
>>>>> image there, but as aforementioned, I've set the directory for these
>>>>> images
>>>>> to be in:
>>>>>
>>>>> Field('image', 'upload', uploadfolder=os.path.join(**requ**
>>>>> est.folder,'uploads/**profiles/'**)
>>>>>
>>>>
>>>> No, the URL /download/image... does not imply web2py is looking the the
>>>> "download" directory. Remember, URLs do not map to directories (with the
>>>> exception of static files). In web2py, URLs always map to applications,
>>>> controllers, and functions. In your URL, it looks like the application and
>>>> controller are excluded, so "download" will be interpreted by web2py as
>>>> the
>>>> function, and then the filename will be interpreted as request.args(0).
>>>> This URL will call the download() function in default.py, which will
>>>> ultimately call response.download(request, db), and that function will
>>>> pull
>>>> the filename from request.args(0).
>>>>
>>>> There is a problem with the filename, though. It starts with "image",
>>>> which appears to be the field name, but it should actually start with
>>>> "[table_name].[field_name]". I'm not sure how that could have happened. Do
>>>> you have the same problem with new images that you upload? Do their
>>>> filenames start with the table name, or just with "image"?
>>>>
>>>> Anthony
>>>>
>>>> --
>>>>
>>>>
>>>>
>>>>
>>>
>>> --
>>
>>
>>
>>
>
>
--