一个基于flask的web应用诞生 用户注册功能开发(5)


Posted in Python onApril 11, 2017

下面把角色分为两种,普通用户和管理员用户,至少对于普通用户来说,直接修改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 "修改用户表"

回车后界面显示内容为:

一个基于flask的web应用诞生 用户注册功能开发(5)

然后进行db差异的改动

python default.py db upgrade

这时看db中的表结构:

一个基于flask的web应用诞生 用户注册功能开发(5)

已经修改成功

注册界面

然后新建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")

代码有点??拢?黄?粒???疽馔寄鼙泶锴宄??δ芤部梢允迪郑??衷诘奈侍饫戳耍?尤胛倚略鲆桓鲎侄危?敲葱枰?薷娜?Υ?耄?tml,form.get,校验),并且尤其是需要修改html,而且html部分没有验证,如果增加客户端验证的话,需要修改的会更多。那么有没有一个针对表单进行优化的工具呢,答案是当然有,轮到wtf登场了。

引入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 %}

执行,输出结果:

一个基于flask的web应用诞生 用户注册功能开发(5)

阿欧,报错了,看看输出是什么错误:

一个基于flask的web应用诞生 用户注册功能开发(5)

注意红线一句,是CSRF错误,CSRF的概念可直接百度,知道问题了,其实也很好修改,在框架中增加一个秘钥就可以有效的防范了,在default.py中增加一行:

app.config['SECRET_KEY'] = "Niu_blog String"

秘钥字符串可自定义

然后再次运行,出现界面:

一个基于flask的web应用诞生 用户注册功能开发(5)

并且包含验证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)

注意此时已删除registerPost方法

好运行测试一下

一个基于flask的web应用诞生 用户注册功能开发(5)

点击提交:

一个基于flask的web应用诞生 用户注册功能开发(5)

阿欧,日期格式为啥不对?这个要从源码里看了:

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,然后点击提交:

一个基于flask的web应用诞生 用户注册功能开发(5)

注意,由于代码中提交成功之后依然是返回到此页,并注入内容,所以显示没有问题,看看db中:

一个基于flask的web应用诞生 用户注册功能开发(5)

记录正常进入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后,成功登录首页

回到首页

现在首页白茫茫的一片,什么内容都没有,正常的轻博客应该登录后显示发博按钮,已关注文章等,但首先要记录登录的状态,这些将在下一章说明。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python简单获取自身外网IP的方法
Sep 18 Python
python实现随机梯度下降(SGD)
Mar 24 Python
解决PyCharm import torch包失败的问题
Oct 13 Python
浅谈pycharm出现卡顿的解决方法
Dec 03 Python
python3的数据类型及数据类型转换实例详解
Aug 20 Python
对python中UDP,socket的使用详解
Aug 22 Python
softmax及python实现过程解析
Sep 30 Python
Django之form组件自动校验数据实现
Jan 14 Python
python logging 日志的级别调整方式
Feb 21 Python
python基于pygame实现飞机大作战小游戏
Nov 19 Python
Flask使用SQLAlchemy实现持久化数据
Jul 16 Python
python使用pycharm安装pyqt5以及相关配置
Apr 22 Python
一个基于flask的web应用诞生 flask和mysql相连(4)
Apr 11 #Python
一个基于flask的web应用诞生 bootstrap框架美化(3)
Apr 11 #Python
一个基于flask的web应用诞生 使用模板引擎和表单插件(2)
Apr 11 #Python
非递归的输出1-N的全排列实例(推荐)
Apr 11 #Python
一个基于flask的web应用诞生(1)
Apr 11 #Python
Python 文件处理注意事项总结
Apr 10 #Python
python非递归全排列实现方法
Apr 10 #Python
You might like
第五节 克隆 [5]
2006/10/09 PHP
php中static静态变量的使用方法详解
2010/06/04 PHP
apache+codeigniter 通过.htcaccess做动态二级域名解析
2012/07/01 PHP
PHP获取一个字符串中间一部分字符的方法
2014/08/19 PHP
PHP对象递归引用造成内存泄漏分析
2014/08/28 PHP
PHP中实现获取IP和地理位置类分享
2015/02/10 PHP
PHP的命令行命令使用指南
2015/08/18 PHP
配置Nginx+PHP的正确思路与过程
2016/05/10 PHP
php自定义函数实现汉字转换utf8编码的方法
2016/09/29 PHP
php中的依赖注入实例详解
2019/08/14 PHP
$()JS小技巧
2007/07/21 Javascript
Google Map V3 绑定气泡窗口(infowindow)Dom事件实现代码
2013/04/26 Javascript
处理及遍历XML文档DOM元素属性及方法整理
2013/08/23 Javascript
DIV始终居中的js代码
2014/02/17 Javascript
深入探密Javascript数组方法
2015/01/08 Javascript
jQuery动态效果显示人物结构关系图的方法
2015/05/07 Javascript
jQuery实现自动调整字体大小的方法
2015/06/15 Javascript
c#程序员对TypeScript的认识过程
2015/06/19 Javascript
基于insertBefore制作简单的循环插空效果
2015/09/21 Javascript
JavaScript学习小结之被嫌弃的eval函数和with语句实例详解
2016/08/01 Javascript
javascript 判断用户有没有操作页面
2017/10/17 Javascript
Vue函数式组件的应用实例详解
2019/08/30 Javascript
vue 兄弟组件的信息传递的方法实例详解
2019/08/30 Javascript
Vue2.0 ES6语法降级ES5的操作
2020/10/30 Javascript
详解Python sys.argv使用方法
2019/05/10 Python
Python3 venv搭建轻量级虚拟环境的步骤(图文)
2019/08/09 Python
python 多线程死锁问题的解决方案
2020/08/25 Python
python制作抽奖程序代码详解
2021/01/15 Python
一款CSS3实现多功能下拉菜单(带分享按)的教程
2014/11/05 HTML / CSS
澳大利亚百货公司:David Jones
2018/02/08 全球购物
为什么要有struct关键字
2012/05/08 面试题
人力资源管理专业应届生求职信
2013/09/28 职场文书
就职演讲稿范文
2014/05/19 职场文书
2014年财务工作总结范文
2014/11/11 职场文书
电工实训心得体会
2016/01/14 职场文书
Netty结合Protobuf进行编解码的方法
2021/06/26 Java/Android