>
> However, I believe (at least in web2py 2.9.12) the first parameter in 
> _after_insert() is NOT a dict, but a Row object. Because, my web2py app 
> uses the following code in db.py, trying to send out a validation email to 
> new registrated user:
>
> def customized_email_verification(row, row_id):
>>
>     db(db.auth_user.id==row_id).update(registration_key="a random 
>> string")  # I need this because my users are not registered from web UI 
>
>     db.commit()  # commit BEFORE the time consuming email action, 
>> otherwise a parallel requests could cause duplicated record in DB?!
>
>     auth.settings.mailer.send(to=row["email"], subject="Hi", 
> *message=customized_message 
>> % row*)
>> db.auth_user._after_insert.append(customized_email_verification)
>
>
> and it ends up with a very confusing error as:
>
> TypeError: format requires a mapping
>
>
> Finally I located that line and changed it into:
>
>     ... customized_message % row.as_dict()
>
>
> and then it works.
>
> So I am asking for your confirmation and suggest to fix the book 
> accordingly.
>

Yes, the first argument is a Row object, so we should probably update the 
book. However, your error is odd because you can generally use a Row object 
in that way without explicitly converting it to a dictionary. What is the 
content of customized_message and the Row object when this error is 
generated?
 

> A followup question. The reason I need my clumsy 
> customized_email_verification() in the first place, is because I seemingly 
> have to do db.commit() BEFORE the time consuming email sending job. 
> Otherwise I saw some randomly duplicated records in my auth_user table. I 
> don't know the exact reason but my guess is, the tools.py's define_tables() 
> uses IS_NOT_IN_DB() validators which only work in web2py level, but does 
> NOT define any "unique=True" in the DB level. Is this considered as a 
> defect?
>

It's not a defect, just something you have to handle properly in your code. 
You can separately set the unique=True argument when creating the model, 
and that will be enforced by the database, but your problem then is that an 
attempted duplicate entry will end up raising an exception and returning a 
500 response unless you catch and handle the error.

Now: the first user creation request is validated but by default not yet 
> committed, and now sending email which will likely take 2 seconds
> Now + 1 second: Somehow the client could resent same request. This request 
> also passes validation, because there is no duplication in DB so far.
> Now + 2 second: The email for request #1 has been sent. And record #1 is 
> committed into DB.
> Now + 3 second: The email for request #2 has been sent. And duplicated 
> record #2 is committed into DB.
>
> How can I improve such pattern? Thanks!
>

You can do the commit early, as you are now, or you could have the email 
sent asynchronously by putting it in a queue (this would also create a 
better user experience, eliminating the long wait).

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 the Google Groups 
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to