下面把角色分为两种,普通用户和管理员用户,至少对于普通用户来说,直接修改 DB 是不可取的,要有用户注册的功能,下面就开始进行用户注册的开发。
首先要想好用户注册的时候需要提供什么信息:用户名、密码、昵称、邮箱、生日、性别、自我介绍,下面就按照这些信息修改用户模型:
- class User(db.Model):
- __tablename__="users"
- id=db.Column(db.Integer,primary_key=True)
- username=db.Column(db.String(50),unique=True,index=True)
- password=db.Column(db.String(50))
- nickname=db.Column(db.String(50))
- email=db.Column(db.String(100))
- birthday=db.Column(db.DateTime)
- gender=db.Column(db.Integer)
- remark=db.Column(db.String(200))
- role_id=db.Column(db.Integer,db.ForeignKey("roles.id"))
然后使用脚本修改 db
- python
- default.py db migrate - m "修改用户表"
回车后界面显示内容为:
然后进行 db 差异的改动
python default.py db upgrade
这时看 db 中的表结构:
已经修改成功
然后新建 register.html 模板,设置登录表单:
- {% extends "base.html"%}
- {% block content %} <!--具体内容-->
- <div class="container">
- <div class="row"></div>
- <div class="row">
- <div>
- <div class="page-header">
- <h1>欢迎您注册</h1>
- </div>
- {% for message in get_flashed_messages() %}
- <div class="alert alert-warning" >
- <button type="button" class="close" data-dismiss="alter">×</button>
- {{message}}
- </div>
- {% endfor %}
- <form method="post">
- <div class="form-group">
- <label for="username">用户名</label>
- <input type="text" class="form-control" name="username" id="username" placeholder="请输入用户名">
- </div>
- <div class="form-group">
- <label for="passworld">密码</label>
- <input type="password" class="form-control" name="password" id="passworld" placeholder="请输入密码">
- </div>
- <div class="form-group">
- <label for="email">昵称</label>
- <input type="email" class="form-control" name="nickname" id="nickname" placeholder="请输入昵称">
- </div>
- <div class="form-group">
- <label for="birthday">生日</label>
- <input type="date" class="form-control" name="birthday" id="birthday" placeholder="请输入生日">
- </div>
- <div class="form-group">
- <label >性别</label>
- <label class="form-control">
- <input type="radio" name="gender" value="0" id="gender0"><label for="gender0">男</label>
- <input type="radio" name="gender" value="1" id="gender1"><label for="gender1">女</label>
- </label>
- </div>
- <div class="form-group">
- <label for="email">电子邮箱</label>
- <input type="email" class="form-control" name="email" id="email" placeholder="请输入电子邮箱">
- </div>
- <button type="submit" class="btn btn-default">登录</button>
- </form>
- </div>
- </div>
- </div>
- {% endblock %}
然后在 default.py 文件中新增 register 路由,代码为:
- @app.route("/register",methods=["GET"])
- def register():
- return render_template("/register.html")
运行界面正常,然后增加 post 路由:
- @app.route("/register",methods=["Post"])
- def registerPost():
- user=User();
- user.username=request.form.get("username","")
- user.password = request.form.get("password", "")
- user.birthday = request.form.get("birthday", "")
- user.email = request.form.get("email", "")
- user.gender = request.form.get("gender", "")
- user.nickname = request.form.get("nickname", "")
- user.role_id = 1 #暂时约定公开用户角色为1
- #判断,其中用户名,密码,昵称不能为空
- if(len(user.username.strip())==0):
- flash("用户名不能为空")
- return render_template("/register.html")
- if(len(user.password.strip())==0):
- flash("用户密码不能为空")
- return render_template("/register.html")
- if (len(user.nickname.strip()) == 0):
- flash("用户昵称不能为空")
- return render_template("/register.html")
- db.session.add(user);
- flash("您已注册成功")
- return render_template("/register.html")
代码有点啰嗦,不漂亮,但基本意图能表达清楚,功能也可以实现,但现在的问题来了,加入我新增一个字段,那么需要修改三处代码(html,form.get, 校验),并且尤其是需要修改 html,而且 html 部分没有验证,如果增加客户端验证的话,需要修改的会更多。那么有没有一个针对表单进行优化的工具呢,答案是当然有,轮到 wtf 登场了。
和之前一样,首先需要安装插件。
- pip3.6 install flask-wtf
然后引入所需的包
- from flask.ext.wtf import Form from wtforms import StringField,
- PasswordField,
- SubmitField,
- RadioField from wtforms.validators import DataRequired,
- EqualTo,
- Length
下面创建一个表单 RegisterForm:
- class RegisterForm(Form):
- username = StringField("请输入用户名", validators=[DataRequired()])
- password = PasswordField("请输入密码", validators=[DataRequired()])
- repassword=PasswordField("确认密码", validators=[EqualTo("password")])
- nickname= StringField("昵称")
- birthday= DateField("出生日期")
- email= StringField("邮箱地址", validators=[Email()])
- gender= RadioField("性别", choices=[("0", "男"), ("1", "女")], default=0)
- remark= TextAreaField("自我简介")
- submit=SubmitField("提交")
修改 register.html 模板:
- {% extends "base.html"%}
- {% block content %} <!--具体内容-->
- {% import "bootstrap/wtf.html" as wtf %} <!--导入bootstrap模板 -->
- <div class="container">
- <div class="row"></div>
- <div class="row">
- <div>
- <div class="page-header">
- <h1>欢迎您注册</h1>
- </div>
- {% for message in get_flashed_messages() %}
- <div class="alert alert-warning">
- <button type="button" class="close" data-dismiss="alter">×</button>
- {{message}}
- </div>
- {% endfor %}
- {{ wtf.quick_form(form)}} <!--创建表单-->
- </div>
- </div>
- </div>
- {% endblock %}
执行,输出结果:
阿欧,报错了,看看输出是什么错误:
注意红线一句,是 CSRF 错误,CSRF 的概念可直接, 知道问题了,其实也很好修改,在框架中增加一个秘钥就可以有效的防范了,在 default.py 中增加一行:
- app.config['SECRET_KEY'] = "Niu_blog String"
然后再次运行,出现界面:
并且包含验证 bootstrap 的验证样式,接下来继续改造 default.py 已完成此注册功能
- @app.route("/register",methods=["GET","POST"])
- def register():
- form=RegisterForm()
- if form.validate_on_submit():
- user=User()
- user.username=form.username.data
- user.password=form.password.data
- user.birthday=form.birthday.data
- user.email=form.email.data
- user.gender=form.gender.data
- user.nickname=form.nickname.data
- user.role_id=1 #暂时约定公开用户角色为1
- db.session.add(user)
- return render_template("/register.html",form=form)
好运行测试一下
点击提交:
阿欧,日期格式为啥不对?这个要从源码里看了:
- class DateField(DateTimeField):
- """
- Same as DateTimeField, except stores a `datetime.date`.
- """
- def __init__(self, label=None, validators=None, format='%Y-%m-%d', **kwargs):
- super(DateField, self).__init__(label, validators, format, **kwargs)
- def process_formdata(self, valuelist):
- if valuelist:
- date_str = ' '.join(valuelist)
- try:
- self.data = datetime.datetime.strptime(date_str, self.format).date()
- except ValueError:
- self.data = None
- raise ValueError(self.gettext('Not a valid date value'))
这个是 wtforms 的 field 的源码,位于 / wtforms/fields/core.py 的 745 行,可以看到,这里支持的日期格式为年 - 月 - 日格式,格式限定比较死,并且文本框没有用 html5 的 date 而是普通的 text,解决办法以后再说,暂时先修改输入,改为 1988-2-5,然后点击提交:
注意,由于代码中提交成功之后依然是返回到此页,并注入内容,所以显示没有问题,看看 db 中:
记录正常进入 db,功能实现完成。
下面改造登录页,首先创建登录表单:
- class LoginForm(Form):
- username=StringField("请输入用户名",validators=[DataRequired()])
- password=PasswordField("请输入密码")
- submit=SubmitField("登录")
修改登录模板页:
- {% extends "base.html"%}
- {% import "bootstrap/wtf.html" as wtf %}
- {% block content %} <!--具体内容-->
- <div class="container">
- <div class="row"></div>
- <div class="row">
- <div class="col-md-4 col-md-offset-4 col-sm-6 col-sm-offset-3">
- <div class="page-header">
- <h1>欢迎您登陆</h1>
- </div>
- {% for message in get_flashed_messages() %}
- <div class="alert alert-warning">
- <button type="button" class="close" data-dismiss="alter">×</button>
- {{message}}
- </div>
- {% endfor %}
- {{ wtf.quick_form(form)}}
- </div>
- </div>
- </div>
- {% endblock %}
修改路由方法:
- @app.route("/login",methods=["GET","POST"])
- def login():
- form=LoginForm()
- if form.validate_on_submit():
- username = form.username.data
- password = form.password.data
- user = User.query.filter_by(username=username, password=password).first()
- if user is not None:
- session["user"] = username
- return render_template("/index.html", name=username, site_name='myblog')
- else:
- flash("您输入的用户名或密码错误")
- return render_template("/login.html",form=form) # 返回的仍为登录页
- return render_template("/login.html",form=form)
重启服务,运行程序,输入 zhangji 和 123 后,成功登录首页
现在首页白茫茫的一片,什么内容都没有,正常的轻博客应该登录后显示发博按钮,已关注文章等,但首先要记录登录的状态,这些将在下一章说明。
来源: http://www.cnblogs.com/jiangchao226/p/6403901.html