zoukankan      html  css  js  c++  java
  • 一个web应用的诞生(5)--数据表单

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

    引入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">&times</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)
    

    注意此时已删除registerPost方法

    好运行测试一下

    点击提交:

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

    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">&times</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后,成功登录首页

    回到首页

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

  • 相关阅读:
    锋利的jQuery书中推荐的几款插件
    60款很酷的 jQuery 幻灯片演示和下载
    关于viewport
    几个Jquery对话框插件
    从小白白到大白白之初识区块链(如何理解区块链)
    简单的MVC与SQL Server Express LocalDB
    java的MVC与C#
    企业微信登陆方式
    整洁的测试遵循的规则
    Android活动的生命周期
  • 原文地址:https://www.cnblogs.com/jiangchao226/p/6403901.html
Copyright © 2011-2022 走看看