Hi,

I am building an application on AppEngine platform. Whenever a user 
requests for an invite, the user is sent an email with a link.
The user when clicks on the link is presented with a registration page 
which contains two forms :

1. Custom Registration form
2. Image upload form for a profile picture. This form is integrated with 
Google Blobstore service.

The user fills in the information. When he clicks on the image upload 
button, he is presented with an overlay containing the image upload form 
where he chooses and adjusts the image he would like to set as his profile 
pic. Once finalized, the overlay is closed and the user now clicks on 
"Complete Registration"
button. The controller then makes the entries in the corresponding tables 
and the user is redirected to his profile page as can be seen from the code 
below.

The code for the custom registration form (controller) is as follows:

    email_id = request.get_vars['email']
    activation_key = request.get_vars['id']
    image_error_msg = ""
    try:
        # Check if its an already existing user
        if dal_db(dal_db.auth_user.email==email_id.lower()).select():
            raise HTTP(404)
        else:
            # Validate the email and activation key
            check_user = 
dal_db(dal_db.Signup.email==email_id).select().first()
            if ((check_user!=None) and (check_user.activation_key!='') and 
(check_user.activation_key!=None) and 
(check_user.activation_key==activation_key)):

                # Define the registration form
                form = SQLFORM(dal_db.auth_user,
                            
fields=['first_name','last_name','location','password'],
                            submit_button='Complete Registration',
                            _id='info',
                            _name='registration'
                        )

                form.custom.widget.password['_checkref']='#showpassword'
                
form.custom.widget.password.requires=dal_db.auth_user.password.requires

                if form.validate(hideerror=True):

                    # Get values from form fields
                    password = form.vars.password
                    first_name = form.vars.first_name
                    last_name = form.vars.last_name
                    location = form.vars.location
                    userFriendsID = request.vars.userFriendsID

                    if (session.profile_image is None) and 
(session.thumb_image is None):
                        image_error_msg = "Required"
                        return 
dict(form=form,image_error_msg=image_error_msg)

                    # Create User object
                    new_user = 
User(email_id.lower(),password,first_name,location,session.profile_image,session.thumb_image)
                    new_user.set_user_extras(last_name)

                    # Define cross transaction options
                    xg_options = db.create_transaction_options(xg=True)

                    # Run the new user insert in transaction
                    registered_id = 
db.run_in_transaction_options(xg_options,new_user.create_user,dal_db)

                    # Make activation key NULL
                    updated_records = 
check_user.update_record(activation_key='',activation_ind='Y')

                    # Auto Login
                    user_dict = new_user.__dict__
                    user_dict['id']=registered_id
                    session.auth = Storage(user=user_dict,
                                        last_visit=datetime.now(),
                                        expiration=auth.settings.expiration,
                                        hmac_key=web2py_uuid())

                    redirect(URL('user','profile'))

                elif form.errors:
                    if form.errors.first_name!=None:
                        form.errors.first_name="First Name cannnot be empty"
                    if form.errors.location!=None:
                        form.errors.location="Please tell us where you live"
                    if form.errors.password!=None:
                        form.errors.password="Please provide atleast 6 
characters"
                else:
                    form.errors.first_name=""
                    form.errors.location=""
                    form.errors.password=""
            else:
                raise HTTP(404)
    except (Error, Exception), ex:
        logger.error("Fatal Error while registering " + str(ex))
        raise HTTP(500)

    return dict(form=form,image_error_msg=image_error_msg)

The image upload form code is derived from the source: 
http://www.web2pyslices.com/slice/show/1388/google-app-engine-blobstore-api-support
and is implemented with modifications as:


    form = SQLFORM(dal_db.blobstore_image, 
fields=['blob_key'],_name='uploadimage')

    # Get the dynamic upload_url for blobstore and set the form action
    upload_url = 
blobstore.create_upload_url(URL(r=request,f='upload_image'))
    form['_action']=upload_url
    (begin, end) = form._xml()
    form.custom.begin = XML("<%s %s>" % (form.tag, begin))

    image_url = ""

    if request.args and request.args[0] and request.args[0]!='-1':
        row = 
dal_db(dal_db.blobstore_image.id==request.args[0]).select().first()
        if row and row.blob_key:
            session.image_id = request.args[0]
            image_url = row.image_url

    elif request.args and request.args[0]=='-1':
        image_url="#"

    blob_info = None
    if request.vars.blob_key == '':
        request.vars.blob_key = None
    if request.vars.blob_key != None:
        blob_info = blobstore.parse_blob_info(request.vars.blob_key)
        del request.vars['blob_key']

    if form.accepts(request.vars,formname="uploadimage"):

        row = dal_db(dal_db.blobstore_image.id == 
form.vars.id).select().first()

        # If the image has been updated, remove the previous image from 
blobstore
        if (blob_info and (row and row.blob_key)):
            blobstore.delete(row.blob_key)
            row.update_record(blob_key=None)

        if blob_info:

            try: 
                # Check for valid extensions
                content_type = blob_info.content_type.split('/')[1]
                if content_type!='jpeg' and content_type!='png':
                    raise Exception("Uploaded image does not have a valid 
content_type")
                elif blob_info.size > 1048576:
                    raise Exception("Uploaded image is greater than 1 MB")
                else:
                    key = blob_info.key()
                    url = get_serving_url(str(blob_info.key()))

                    uploaded_image = images.Image(blob_key=blob_info.key())
                    uploaded_image.rotate(360)
                    if (blob_info.content_type).split('/')[1]=='jpeg':
                        
uploaded_image.execute_transforms(output_encoding=images.JPEG)
                    else:
                        uploaded_image.execute_transforms()

                    if uploaded_image.width < 300 or uploaded_image.height 
< 300:
                        raise Exception("Image size less than 300x300")

                    session.image_width = uploaded_image.width
                    session.image_height = uploaded_image.height
                    
                    logger.debug(str(session.image_width))
                    logger.debug(str(session.image_height))
                    
                    row.update_record(blob_key = key,image_url = url)

            except (Error,Exception), err:
                logger.debug("Exception Raised: " + str(err))
                blobstore.delete(blob_info.key())
                raise HTTP(303,Location= 
URL(r=request,f='upload_image',args='-1'))

        raise HTTP(303,Location= URL(r=request,f='upload_image', 
args=form.vars.id))

    elif form.errors:
        logger.info(str(form.errors))
        if blob_info:
            blobstore.delete(blob_info.key())
        raise HTTP(303,Location= URL(r=request,f='upload_image',args='-1'))

    return dict(form=form,image_url=image_url)


In the view the image upload form is included as a component with ajax=False
For implementing the ajax functionality for uploading profile image we are 
using ajaxForm of http://jquery.malsup.com/form/

The code for the .load component is :

{{if image_url=="":}}
    <span id="greetingmsg">Please upload a (JPG,PNG) image of minimum 
300x300 px and a maximum size of 5MB</span>
{{else:}}
    <table>
        <tr>
            <td><img src="{{=image_url}}" id="selectedphoto"/></td>
            <td><div id="previewBox"><img src="{{=image_url}}" 
id="preview"/></div></td>
        </tr>
    </table>
    <span id="greetingmsg"></span>
    <span id="photocoord">
        <input type="hidden" id="x" name="x"/>
        <input type="hidden" id="y" name="y"/>
        <input type="hidden" id="w" name="w"/>
        <input type="hidden" id="h" name="h"/>
        <a href="#" id="coord">Done</a>
    </span>  
    {{pass}}
    
{{=form.custom.begin}}
    {{=form.custom.widget.blob_key}}    
{{=form.custom.end}}

<script language="javascript" type="text/javascript">
    $(document).ready(function(){
        $('form').ajaxForm({target:'#target'});
        $('input[name=blob_key]').change(function(){            
            $('#greetingmsg').html('Uploading...');
            $('#target form').submit();
        });
        
        {{if image_url!="":}}            
            $('#selectedphoto').Jcrop({
                minSize: [300,300],
                boxWidth: 440,
                boxHeight: 330,
                setSelect: [300, 300, 0, 0 ],
                aspectRatio: 1,
                onChange: updatePreview
            },function(){
                // Use the API to get the real image size
                var bounds = this.getBounds();
                boundx = bounds[0];
                boundy = bounds[1];
                $('#photocoord').show();
                
$('#photoUpload').css({'margin-left':-($('#photoUpload').width()/2+30)});
            });        
            $('#previewBox').css({width:'300px', height:'300px', 
overflow:'hidden'});
            
$('#photoUpload').css({'margin-left':-($('#photoUpload').width()/2+30)});
            $('#photocoord a').click(function(){
                //$('span.temp').html('Saving Image');
                ajax('create_profile_pic', ['x','y','w','h'], ':eval');
                return false;
            });
            {{pass}}        
    });
</script>


*The Problem:*

When the user clicks on "Complete Registration" button, the code redirects 
to the profile page as we can see in the GAE server logs

INFO     2012-06-14 15:43:31,057 dev_appserver.py:2891] "POST 
/devekayan*/registration/activate?email=sushant.tanej...@gmail.com&id=755047905ed0e8df1d90cfa687ca0f4986d1e946
 
HTTP/1.1" 303 -*
INFO     2012-06-14 15:43:31,242 gaehandler.py:69] **** Request: 
149.23ms/150.00ms (real time/cpu time)
INFO     2012-06-14 15:43:31,248 recording.py:486] Saved; key: 
__appstats__:011000, part: 60 bytes, full: 6092 bytes, overhead: 0.000 + 
0.005; link: http://localhost:8080/_ah/stats/details?time=1339688611093
INFO     2012-06-14 15:43:31,266 dev_appserver.py:2891] "GET 
/devekayan*/user/profile 
HTTP/1.1" 200 -*
INFO     2012-06-14 15:43:31,322 dev_appserver.py:2891] "GET 
/devekayan/static/js/jquery.js?_=1339688611296 HTTP/1.1" 200 -
INFO     2012-06-14 15:43:31,460 dev_appserver.py:2891] "GET 
/devekayan/static/js/web2py.js?_=1339688611425 HTTP/1.1" 200 -
INFO     2012-06-14 15:43:31,508 dev_appserver.py:2891] "GET 
/devekayan/static/js/jquery.easing.js?_=1339688611466 HTTP/1.1" 200 -
INFO     2012-06-14 15:43:31,547 dev_appserver.py:2891] "GET 
/devekayan/static/js/jquery.form.js?_=1339688611518 HTTP/1.1" 200 -


But on the client side nothing happens. (i.e. the user remains on the 
registration page itself). The profile page is not loaded at all.
The problem started occurring only after we integrated the blobstore 
service. Earlier we were storing images in datastore and everything was 
working fine.

I have reproduced the problem in production and on both Chrome and Firefox 
browers.

Can anyone tell me what might be the problem ?

Thanks,
Sushant Taneja



Reply via email to