Ajax and Auth API

408 views
Skip to first unread message

Yannick

unread,
Mar 24, 2010, 10:32:59 AM3/24/10
to web2py-users, Massimo Di Pierro
Hello mate,
This can be an easy question but I don't know how to used the Web2py
"Ajax (u,s,t)" function to call build-in Web2py Authentication API.
It's there any example ?...

There is a cool example using JDiv:
def register():
return auth.register(onaccept=lambda form: jDiv.flash('try
login'))

This is cool BUT I DON'T want to use jDiv...
How can I do the same without using JDIV... But instead i want to use
AJAX(u,s,t){} function just like any other form that use Ajax function
to send value ( The only difference here is the fact that I'll send
value to already build Auth API like auth.register(),
auth.password_change(), auth.login() etc... )


Please let me know if you have any hints.

Yannick P.

mdipierro

unread,
Mar 24, 2010, 11:16:02 AM3/24/10
to web2py-users
You should make your own action and use {{=LOAD(..)}}

Yannick

unread,
Mar 24, 2010, 12:06:47 PM3/24/10
to web2py-users
Sorry I really don't understand... I have to code my own Auth function
like "register(), login() etc..." it that what you meant ?

Yes I know I have to create my own action but I wanted to re-use the
Auth Api function by calling them inside my action...
So basically what you are saying is that i can't do it that way ?

Please let me know if I'm missing something here...

Thanks a lot,
Yannick P.

mdipierro

unread,
Mar 24, 2010, 12:11:42 PM3/24/10
to web2py-users
show us your action and explan how you want it to behave in details,
and I can post an example.

Yannick

unread,
Mar 24, 2010, 1:22:19 PM3/24/10
to web2py-users
Ok here is a view form to change user password:
###################################################
<script>
$("#pwdChangeForm").submit(function(){
url={{=URL(r=requet, f="changePwd")}};
ids = ['currentpwd', 'pwd1', 'pwd2'];
ajax(url, ids, 'confirmationMsg'); # This is the Ajax method that
is coming with Web2py
return false;
});
</script>

<div id="confirmationMsg"></div>
<form id="pwdChangeForm" method="post">
Current password: <input type="password" id="currentpwd"
name="currentpassword">
new password: <input type="password" id="pwd1"
name="password1">
Old password: <input type="password" id="pwd2"
name="password2">
<input type="submit" value="Submit">
</form>
######################################
# Action: (Here I want to use the Auth method named change_password. )
##############################
def changePwd:
return auth.change_password()

So basically from the action I wanted to be able to know when the form
is validated and return a confirmation that will be display through
AJAX. I hope you understand what I mean here... Instead of returning a
form, I want to return a string that represent a success or an Error
message... How can I do that without the need to create my how code to
change the password . Thanks!

Yannick P.

mdipierro

unread,
Mar 24, 2010, 2:00:55 PM3/24/10
to web2py-users
###################################################
<script>
$("#pwdChangeForm").submit(function(){
url={{=URL(r=requet, f="changePwd")}};
ids = ['currentpwd', 'pwd1', 'pwd2'];
ajax(url, ids, 'confirmationMsg'); # This is the Ajax method that
is coming with Web2py
return false;
});

</script>

In view:
{{=LOAD('defualt','changePwd',ajax_trap=True)}}

######################################
# Action: (Here I want to use the Auth method named change_password. )
##############################
def changePwd:

next = URL(r=request,f='index')
return auth.change_password(onaccept=lambda form:\
response.headers['web2py-component-
command'="document.location='%s'" % next)

Yannick

unread,
Mar 24, 2010, 9:21:12 PM3/24/10
to web2py-users
Sorry but I have a lot of syntax error in the action:

auth.change_password(onaccept=lambda form: response.headers['web2py-
component-command']="document.location='%s'"%next))

I don't seems to see why... Please let me know if you see it...
Thanks,

mdipierro

unread,
Mar 24, 2010, 10:17:57 PM3/24/10
to web2py-users
My bad

auth.change_password(onaccept=lambda form:
response.headers.update({'web2py-
component-command']:"document.location='%s'"%next}))

Yannick

unread,
Mar 25, 2010, 12:58:34 PM3/25/10
to web2py-users

Hello thanks Massimo for the note... But I can't make it work... the
change_password() doesn't change the value in the DB... So I tried
other function just to test like "register()" and in this case i even
have an error message saying "TypeError: list objects are
unhashable"... I really don't know what I'm doing wrong up here...
Below it's the controller and view... Please let me know if you have
any idea...

#################
#View "index.html"
#################
.....
.....
{{=LOAD('default','register',ajax_trap=True)}}
.....
.....
###################
#Controller: "default.py"
###################
def register():


next = URL(r=request,f='index')

return auth.register(onaccept=lambda form:


response.headers.update({['web2py-component-
command']:"document.location='%s'"%next}))

def otherAction():
.....
.....
return dict(..........)

def index():
return (register = register(), otherAction=otherAction())

#########################
# Here is the error message
########################
Traceback (most recent call last):
File "gluon/restricted.py", line 173, in restricted
File "C:/Documents and Settings/YannickT/web2py/applications/events/
controllers/default.py", line 70, in <module>
File "gluon/globals.py", line 96, in <lambda>
File "C:/Documents and Settings/YannickT/web2py/applications/events/
controllers/default.py", line 27, in register
File "gluon/tools.py", line 1271, in register
File "C:/Documents and Settings/YannickT/web2py/applications/events/
controllers/default.py", line 27, in <lambda>
TypeError: list objects are unhashable

Thanks for your help,
Yannick P.

mdipierro

unread,
Mar 25, 2010, 1:19:06 PM3/25/10
to web2py-users
One more try

def register():
next = URL(r=request,f='index')
return auth.register(onaccept=lambda
form:response.headers.update({'web2py-component-
command':"document.location='%s'"%next}))

Yannick

unread,
Mar 25, 2010, 8:27:48 PM3/25/10
to web2py-users
Thanks for the note... But I tried it, I don't have the error anymore
but the data is not saved in the DB... I run in debug mode and put and
break point in my action "def register():" and I notice that the form
validation is not successful in the method "register()" of the Class
Auth() of "Tools.py"... I have no clue why it fails... The same value
works fine (recorded in DB) without the AJAX...

If you have any hint please let me know... I search a lot in the
threads of this Web2py group and I can't find an example of how to
used Auth Api with Ajax...

Yannick P.

mdipierro

unread,
Mar 25, 2010, 8:49:56 PM3/25/10
to web2py-users
I think something else must be interfering with the session formkeys.
I would need to look at the complete action and view.

Yannick

unread,
Mar 25, 2010, 11:39:26 PM3/25/10
to web2py-users
Thanks. Here is the complete action:

############################################
# I'm testing the registration with Ajax and here
# is my simple Controller
############################################
from applications.TestApp.modules.ControllerUtils import *
controlUtils = ControllerUtils(db)

# Registration Setting Information
auth.settings.registration_requires_verification = False
auth.settings.registration_requires_approval = False


def updateInfo(form):
setTrue = True
setFalse = False
# Create a brand new album for each newly created account
feedback = db.album.insert(buacct_fk = session.auth.user.id,
albumname="Default", albumdesc="This
is your default Album",
albumviewprv=setFalse,
albumactif=setTrue)

# Send a welcome email
controlUtils.sendEmail(form.vars.email,
'Welcome to ',
'Enjoy the journey'
)
return dict()

auth.settings.register_onaccept = updateInfo

def register():
auth.settings.table_user.delete_email.writable = False
auth.settings.table_user.acct_frozen_cmt.writable = False
auth.settings.table_user.accountFrozen.writable = False
auth.settings.table_user.creationTime.writable = False
auth.settings.table_user.language.writable = False
auth.settings.table_user.birthday.writable = False
auth.settings.table_user.delete_email.readable = False
auth.settings.table_user.acct_frozen_cmt.readable = False
auth.settings.table_user.accountFrozen.readable = False
auth.settings.table_user.creationTime.readable = False
auth.settings.table_user.birthday.readable = False
auth.settings.table_user.language.readable = False


next = URL(r=request,f='index')
return auth.register(onaccept=lambda
form:response.headers.update({'web2py-component-
command':"document.location='%s'"%next}))

def index():
return dict(register = register())


########################################################
# The View "index.html": Very simple since i'm testing registration
with Ajax...
########################################################
<div>
<br/>
<br/>
{{=LOAD('BuRegAuth', 'register', ajax_trap=True)}}
</div>

#####
And also I notice that everything is displayed as textfield, How can I
have more control, about being able to display some fields as drop
down etc...
I also notice that this below have NO effect :
- auth.settings.table_user.birthday.writable = False
- auth.settings.table_user.birthday.readable = False
(the fields still appear in the form)


Thanks for your help.

Yannick P.

mdipierro

unread,
Mar 26, 2010, 12:02:35 AM3/26/10
to web2py-users
You have two problems:

1) you are calling register twice. In index() and the LOAD callback.
That generates two forms and confuses web2py on which one you are
submitting. So index should just be

2) You specify onaccept both in settings and as argument of the
register function. The latter overrides the former.

Bottom line: replace this

auth.settings.register_onaccept = updateInfo
...
def register():
...


return auth.register(onaccept=lambda
form:response.headers.update({'web2py-component-
command':"document.location='%s'"%next}))

...


def index():
return dict(register = register())

with this

# auth.settings.register_onaccept = updateInfo
...
def register():
...
return auth.register(onaccept=lambda
form:(updateinfo(form),response.headers.update({'web2py-component-
command':"document.location='%s'"%next})))
...
def index():
return dict()

> ...
>
> read more »

Yannick

unread,
Mar 26, 2010, 7:49:42 AM3/26/10
to web2py-users
Thanks Massimo, Yes it's working now... Thousand thanks... BUT I still
don't know how I can have more control on the display of each field:
Like it's possible to load each field and display them as I want ?

- And I also wanted to know how to catch the error messages so I can
display them like I want... Like being able to get the error message
like this:
{{if formname.errors.email:}} Email {{=formname.errors.email}}
{{pass}}

Please let me know, I feel like I don't have much flexibility for form
displayed other than putting this in the client side


"{{=LOAD('BuRegAuth', 'register', ajax_trap=True)}} "

Thanks a lot for your help,
Yannick P.

> ...
>
> read more »

mdipierro

unread,
Mar 26, 2010, 9:21:21 AM3/26/10
to web2py-users
You just need a view for register.html that does not extend layout and
contains a custom form.

> ...
>
> read more »

Yannick

unread,
Mar 27, 2010, 11:10:48 AM3/27/10
to web2py-users
Hello Massimo, First thanks for you help... I'm stil not successful
with customizing the form for Auth Api using Ajax. Please let me know
what I'm doing wrong... Here is my view and controller (I did not
extend Layout.html)

#############
# Register.html
##############
<html>
<script>
$('#regForm').submit(function(){
url = "{{=URL(r=request, f='register')}}";
ids = [ 'auth_user_fullname', 'auth_user_email',
'auth_user_password', 'auth_user_password_2' ];
ajax(url, ids , 'registerMsg');
});

// I took this from Web2py_ajax just for testing this Register
function ajax(u,s,t) {
var query="";
for(i=0; i<s.length; i++) {
if(i>0) query=query+"&";
query=query+encodeURIComponent(s[i])
+"="+encodeURIComponent(document.getElementById(s[i]).value);
}
jQuery.ajax({type: "POST", url: u, data: query, success:
function(msg) { if(t==':eval') eval(msg); else
document.getElementById(t).innerHTML=msg; } });
}
</script>


<div id="registerMsg"> </div>
<div>
<form action="" id="regForm" enctype="multipart/form-data"
method="post">
Full Name: <input class="string" id="auth_user_fullname"
name="fullname" type="text" value="" />
Email: <input class="string" id="auth_user_email" name="email"
type="text" value="" />
Password: <input class="password" id="auth_user_password"
name="password" type="password" value="" />
Verify Pwd: <input name="password_two" id="auth_user_password_2"
type="password" />


<input type="submit" value="Submit" />

</form>
</div>

</html>

##############
# Controller
##############

def register():
auth.settings.table_user.last_name.writable=False
auth.settings.table_user.last_name.readable=False

next = URL(r=request,f='index')
return auth.register(onaccept=lambda form:

(updateInfo(form),response.headers.update({'web2py-component-


command':"document.location='%s'"%next})))


#########################

When doing this my view has no control on the display, it's like the
form return from the register Action overwritte everything... Can you
please let me know when I'm wrong here...
Thanks,
Yannick P.

mdipierro

unread,
Mar 27, 2010, 8:36:07 PM3/27/10
to web2py-users
IF, as I assume, the register action is called via the
{{=LOAD('controller','register')}} helper THEN

there should be no ajax handling in register.html. It should just be:

{{=form.custom.begin}}


Full Name: <input class="string" id="auth_user_fullname"
name="fullname" type="text" value="" />
Email: <input class="string" id="auth_user_email" name="email"
type="text" value="" />
Password: <input class="password" id="auth_user_password"
name="password" type="password" value="" />
Verify Pwd: <input name="password_two" id="auth_user_password_2"
type="password" />
<input type="submit" value="Submit" />

{{=form.custom.end}}

Moreover all the INPUT fields in the custom form must have names as
the corresponding fields in auth_user table and all required fields i
auth_user MUST be present in the custom form.

Moreover since you form is using


<input class="string" id="auth_user_fullname" name="fullname"
type="text" value="" />

instead of {{=form.custom.widget.fullname}} (assuming you do have a
field called fullname, which is not there in the default) you will
have to handle manually all error reporting.

Yannick

unread,
Mar 30, 2010, 9:06:31 PM3/30/10
to web2py-users
Thanks for the note.... I followed your instructions step by step
unfortunately even this solution doesn't work... the Action dictate
the display, I have NO control on the view...

#
#here is the view Register.html:
#

{{=form.custom.begin}}
Full Name: <input class="string" id="auth_user_fullname"
name="fullname" type="text" value="" />
Email: <input class="string" id="auth_user_email" name="email"
type="text" value="" />
Password: <input class="password" id="auth_user_password"
name="password" type="password" value="" />
Verify Pwd: <input name="password_two" id="auth_user_password_2"
type="password" />
<input type="submit" value="Submit" />
{{=form.custom.end}}

#
# Here is the action
#
def register():
...


next = URL(r=request,f='index')
return auth.register(onaccept=lambda form:
(updateInfo(form),response.headers.update({'web2py-component-
command':"document.location='%s'"%next})))

Whatever I enter in the view will not be display NOTHING, only the
registration form return from the action will be displayed... It's
like the form from the action override everything html code I
enter...

I'm kind of desperate... If you have any other idea please let me
know... Or if you know a place where there is a working example please
send me a link... In the meantime I'll just drop this Auth API -
Ajax...

Thanks a lot for your help...
Yannick P.

mdipierro

unread,
Mar 30, 2010, 9:35:39 PM3/30/10
to web2py-users
One more try.. closer to the solutions...

view as before and action

def register():
...
next = URL(r=request,f='index')

return dict(form=auth.register(onaccept=lambda form:
(updateInfo(form),response.headers.update({'web2py-component-
command':"document.location='%s'"%next}))))

Yannick

unread,
Mar 31, 2010, 11:31:18 PM3/31/10
to web2py-users
Thanks Massimo for the note, I really appreciate your help... Now I
have more control on the layout using your latest change thx... BUT
there are few problems... the "next " doesn't seems to work.... I
have to do this:

1)
- auth.settings.register_next= URL(r=request,c='controller',
f='index') to actually go where I want to go right after a successful
registration...

If i only do this in the action :
- next = URL(r=request,c='controller', f='index')


return dict(form=auth.register(onaccept=lambda form:
(updateInfo(form),response.headers.update({'web2py-component-
command':"document.location='%s'"%next}))))

After a registration the page will be redirect to "http://
127.0.0.1:8000/App/default/index"...

2)
Also for the login using Auth and Ajax, when I enter a username and
fake password the page is also redirect to "http://127.0.0.1:8000/App/
default/index". (I put the code to handle the error, I wonder why the
page get redirect instead of returning an error msg)

3)
Also for the registration, when there is an error in the registration
form, I handle the errors BUT the form returned is empty... i was
wondering how to keep the data in the form returned when there is an
error... something like "Keepvalue= true"... I hope you understand
what I mean...


Thanks and please let me know if you have any idea,

Yannick P.

Osman Masood

unread,
Sep 2, 2012, 5:54:40 PM9/2/12
to
I know this thread is 2 years old, but this blog post explains how to do AJAX login/register/forgot password in web2py without LOAD:


It's pretty easy to see how to extend the functionality to include AJAX support for forgot_username and other auth functions (logout, etc.), as well.

Thanks
Reply all
Reply to author
Forward
0 new messages