web2py Custom User Profile?
Asked Answered
F

1

11

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!

Faydra answered 19/8, 2011 at 11:53 Comment(0)
D
16

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.

Dissenter answered 19/8, 2011 at 14:38 Comment(2)
Thanks, Anthony! You're right, there is some official documentation there, and your solution is better than mine. It all seems to fit nicely. One extra thing I noticed was that when I defined my custom table with a username field, username was used for login instead of email. This is what I wanted, and the book says it's built-in behaviour, which is extra nice! Thanks for clearing all that up.Faydra
No problem. Note, if you want to change the label for the username field in the Auth forms, you can specify the label via auth.messages.label_username (it defaults to "Username").Dissenter

© 2022 - 2024 — McMap. All rights reserved.