8.4 用户注册

  • 用户注册的界面,和注册POST请求共用同一个视图函数,兼容POST,GET请求。

  • 表单验证的结果数据,赋值到User模型里,可以在Base类里编写一个set_attrs函数,统一将属性拷贝赋值。动态赋值。

  • 验证器中还应该加入业务逻辑的校验,如email不能重复,这需要自己定义验证器,以vaildate_开头

  • 使用filter_by自定义数据库查询

  • 数据库的密码,前端传来的是明文,需要密文加密到数据库,应该给User的password提供getter/setter函数。在set值的时候,将password加密在赋值给User的_password。

  • 使用db.session,采用ORM方式将数据存储到数据库

  • 如果登录成功,则重定向到登录界面

web/auth.py

@web.route('/register', methods=['GET', 'POST'])
def register():
    form = RegisterForm(request.form)
    if request.method == 'POST' and form.validate():
        user = User()
        user.set_attrs(form.data)

        db.session.add(user)
        db.session.commit()

    return render_template('auth/register.html', form={'data': {}})

models/user.py

class User(Base):
    id = Column(Integer, primary_key=True)
    nickname = Column(String(24), nullable=False)
    _password = Column('password', String(128))
    phone_number = Column(String(18), unique=True)
    email = Column(String(50), unique=True, nullable=False)
    confirmed = Column(Boolean, default=False)
    beans = Column(Float, default=0)
    send_counter = Column(Integer, default=0)
    receive_counter = Column(Integer, default=0)
    wx_open_id = Column(String(50))
    wx_name = Column(String(32))

    @property
    def password(self):
        return self._password

    @password.setter
    def password(self, raw):
        self._password = generate_password_hash(raw)

models/base.py

db = SQLAlchemy(query_class=Query)


class Base(db.Model):
    __abstract__ = True
    status = Column(SmallInteger, default=1)

    def set_attrs(self, attrs_dict):
        for key, value in attrs_dict.items():
            if hasattr(self, key) and key != 'id':
                setattr(self, key, value)

forms/auth.py

class RegisterForm(Form):
    email = StringField(validators=[
        DataRequired(), Length(8, 64, message='电子邮箱不符合规范')])

    nickname = StringField('昵称', validators=[
        DataRequired(), Length(2, 10, message='昵称至少需要两个字符,最多10个字符')])

    password = PasswordField('密码', validators=[
        DataRequired(), Length(6, 20)])

    def validate_email(self, field):
        # User.query.filter_by(email=field.data).first() 等同于 select * from user where name = field.data limit 1
        if User.query.filter_by(email=field.data).first():
            raise ValidationError('电子邮件已被注册')

    def validate_nickname(self, field):
        if User.query.filter_by(nickname=field.data).first():
            raise ValidationError('昵称已存在')

Last updated