User DataModels¶
Flask-User distinguishes between the following groups of user information:
- User Authentication information such as username and password
- User Email information such as email address and confirmed_at
- User information such as first_name and last_name
- User Role information
Flask-User allows the developer to store Authentication, Email and User information in one DataModel or across several DataModels.
Flask-User requires User Role information to be stored in a Role DataModel and an UserRole association table.
All-in-one User DataModel¶
If you’d like to store all user information in one DataModel, use the following:
# Define User model. Make sure to add flask_user UserMixin !!!
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
# User Authentication information
username = db.Column(db.String(50), nullable=False, unique=True)
password = db.Column(db.String(255), nullable=False, default='')
# User Email information
email = db.Column(db.String(255), nullable=False, unique=True)
confirmed_at = db.Column(db.DateTime())
# User information
is_enabled = db.Column(db.Boolean(), nullable=False, default=False)
first_name = db.Column(db.String(50), nullable=False, default='')
last_name = db.Column(db.String(50), nullable=False, default='')
def is_active(self):
return self.is_enabled
# Setup Flask-User
db_adapter = SQLAlchemyAdapter(db, User) # Register the User model
user_manager = UserManager(db_adapter, app) # Initialize Flask-User
Separated User/UserAuth DataModel¶
If you’d like to store User Authentication information separate from User information, use the following:
# Define User DataModel
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
# User email information
email = db.Column(db.String(255), nullable=False, unique=True)
confirmed_at = db.Column(db.DateTime())
# User information
is_enabled = db.Column(db.Boolean(), nullable=False, default=False)
first_name = db.Column(db.String(50), nullable=False, default='')
last_name = db.Column(db.String(50), nullable=False, default='')
def is_active(self):
return self.is_enabled
# Define UserAuth DataModel. Make sure to add flask_user UserMixin!!
class UserAuth(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer(), db.ForeignKey('user.id', ondelete='CASCADE'))
# User authentication information
username = db.Column(db.String(50), nullable=False, unique=True)
password = db.Column(db.String(255), nullable=False, default='')
# Relationships
user = db.relationship('User', uselist=False, foreign_keys=user_id)
# Setup Flask-User
db_adapter = SQLAlchemyAdapter(db, User, UserAuthClass=UserAuth)
user_manager = UserManager(db_adapter, app)
UserEmail DataModel¶
Separating User Email information from User information allows for support of multiple emails per user.
It can be applied to both the All-in-one User DataModel and the separated User/UserAuth DataModel
# Define User DataModel. Make sure to add flask_user UserMixin !!!
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
...
# Relationship
user_emails = db.relationship('UserEmail')
# Define UserEmail DataModel.
class UserEmail(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
# User email information
email = db.Column(db.String(255), nullable=False, unique=True)
confirmed_at = db.Column(db.DateTime())
is_primary = db.Column(db.Boolean(), nullable=False, default=False)
# Relationship
user = db.relationship('User', uselist=False)
User Roles DataModel¶
The Roles table holds the name of each role. This name will be matched to the @roles_required function decorator in a CASE SENSITIVE manner.
# Define the Role DataModel
class Role(db.Model):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(50), unique=True)
The UserRoles DataModel associates Users with their Roles.
It can be applied to both the All-in-one User DataModel and the separated User/UserAuth DataModel
# Define the User DataModel. Make sure to add flask_user UserMixin!!
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
...
# Relationships
roles = db.relationship('Role', secondary='user_roles',
backref=db.backref('users', lazy='dynamic'))
# Define the UserRoles DataModel
class UserRoles(db.Model):
id = db.Column(db.Integer(), primary_key=True)
user_id = db.Column(db.Integer(), db.ForeignKey('user.id', ondelete='CASCADE'))
role_id = db.Column(db.Integer(), db.ForeignKey('role.id', ondelete='CASCADE'))
Porting Flask-User v0.5 applications to Flask-User v0.6¶
For applications using the All-in-one User DataModel, no changes are required.
For applications using the separated User/UserAuth DataModel, v0.6 maintains backward compatibility, but future versions may not, and it is therefore recommended to make the following changes:
- Change
SQLAlchemyAdapter(db, User, UserProfile=UserProfile)
toSQLAlchemyAdapter(db, UserProfile, UserAuth=User)
. - Move the UserMixin from
class User(db.Model)
toclass UserProfile(db.Model, UserMixin)
- Move the
roles
relationship from class User to class UserProfile. - Move the UserRoles.user_id association from ‘user.id’ to ‘user_profile.id’. This requires a DB schema change.
- If it’s possible to rename table names, please rename User to UserAuth and UserProfile to User. This would require a DB schema change.