Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

web2py Custom User Profile?

Tags:

profile

web2py

What is the 'correct' way to extend the base auth_user table/the whole auth system in order to support a number of custom user profile fields (such as username, location, birthday, etc.)?

I've caught glances of approaches from Googling, but no one ever seems to give a straight answer. The answer seems to be either completely replacing the base auth_user table with a custom one (and letting the auth system know), or creating a new extension table with a foreign key reference back to the base auth_user table. The first seems to have reusability problems, the second is going to have problems with forms and such.

Does anyone have any pointers to patch in something as universal as custom user profiles without breaking too much?

EDIT: A bit more reading suggests overriding the base auth_user table is the way to go, and after some trial and error, I've found it's as easy as dropping in a block of code:

# before define_tables()
auth.settings.table_user = db.define_table('auth_user',
    Field('email', length=128,label=T('Email'), default='', unique=True),
    Field('user_name', length=128, label=T('User name'), default='', unique=True, 
        requires=IS_NOT_IN_DB(db, 'auth_user.user_name')
    ),
    Field('password', 'password', readable=False, label=T('Password'),
        requires=CRYPT()
    ),
    Field('first_name', length=128, label=T('First name'), default='',
        requires=(IS_NOT_EMPTY(error_message=auth.messages.is_empty),
        IS_NOT_IN_DB(db, 'auth_user.first_name'))
    ),
    Field('last_name', length=128, label=T('Last name'), default='',
        requires=(IS_NOT_EMPTY(error_message=auth.messages.is_empty),
        IS_NOT_IN_DB(db, 'auth_user.last_name'))
    ),
    Field('registration_key', length=128, default='', writable=False, readable=False),
    Field('country', 'string', length=15, label=T('Country'),
        requires=IS_NULL_OR(IS_IN_SET(('England')))
    ),
)

So long as this gets executed after auth = Auth(db) and before auth.define_tables() in models/db.py, it all seems to work out okay. The fields show up on the user profile page, and everything else still works as expected.

Not sure how to answer my own question, so in the meantime, if someone could explain why this is the right way to do it, and what else must be kept in mind, I'd appreciate it!

like image 708
orlade Avatar asked Aug 19 '11 11:08

orlade


1 Answers

auth.settings.table_user_name stores the name of the user table (which defaults to auth_user), and auth.settings.table_user is a reference to the user table itself. Those two settings are used elsewhere in the Auth code, so that's why it is important to update them when you create a custom user table (in your case, you don't need to update auth.settings.table_user_name because you kept the default name). There is a section in the book demonstrating this method of customizing Auth tables.

Note, if you just want to add some extra fields to the default auth_user table, instead of redefining the entire table as you have done, you can simply do:

auth.settings.extra_fields[auth.settings.table_user_name] = [Field('myfield1',...),
    Field('myfield2',...), etc.]

before calling auth.define_tables(), and those extra fields will be appended to the auth_user table. Note, if there are some fields in the default auth_user table that you simply don't want to use, you can hide them in registration and profile forms by setting their readable and writable attributes to False.

like image 93
Anthony Avatar answered Oct 18 '22 17:10

Anthony