On Wednesday, April 15, 2015 at 5:11:22 PM UTC-7, Anthony wrote: > > 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? >
Thanks for the hint, Anthony. You are right, normally "Welcome %(first_name)s" % row will just work. In my case, it looks like the error also has some something to do with the i18n, although I did not really use the translation feature. This is the last part of the error trace. File "C:\REPO\web2py\applications\v1\models\db.py", line 134, in email_verification message=auth.messages.verify_email % row # .as_dict() File "C:\REPO\web2py\gluon\tools.py", line 468, in send elif message.strip().startswith('<html') and \ File "C:\REPO\web2py\gluon\languages.py", line 403, in __getattr__ return getattr(str(self), name) File "C:\REPO\web2py\gluon\languages.py", line 379, in __str__ self.T.translate(self.m, self.s)) File "C:\REPO\web2py\gluon\languages.py", line 937, in translate message = self.params_substitution(message, symbols) File "C:\REPO\web2py\gluon\languages.py", line 914, in params_substitution message = message % symbols TypeError: format requires a mapping The message is the default "Welcome %(first_name)s! Click on the link %(link)s to verify your email". The symbols is, interestingly, a TUPLE containing only one item, which is the string representation of the Row. It looks like: ("<Row \x1e'first_name': 'Ray', ..., 'link': 'http://...'\x1f>",) No wonder. Now we can use the following line to demonstrate the problem. >>> "Welcome %(first_name)s, pls click %(link)s" % ("whatever string",) TypeError: format requires a mapping I did not further investigate what goes wrong inside the languages.py. > >> 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, > I know I can always define my OTHER tables properly. But now we are talking about the web2py built-in auth_user table. Do I have to redefine them in my models/db.py EVERY TIME I start a new project? That doesn't sound right. Is there any reason we don't want to do that inside gluon/tools.py? > 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. > I can do this part. > > >> 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.