下面把角色分為兩種桐臊,普通用戶和管理員用戶轴合,至少對于普通用戶來說,直接修改DB是不可取的平酿,要有用戶注冊的功能讯檐,下面就開始進(jìn)行用戶注冊的開發(fā)。
用戶表
首先要想好用戶注冊的時候需要提供什么信息:用戶名染服、密碼、昵稱叨恨、郵箱柳刮、生日、性別痒钝、自我介紹秉颗,下面就按照這些信息修改用戶模型:
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 "修改用戶表"
回車后界面顯示內(nèi)容為:
然后進(jìn)行db差異的改動
python default.py db upgrade
這時看db中的表結(jié)構(gòu):
已經(jīng)修改成功
注冊界面
然后新建register.html模板栅隐,設(shè)置登錄表單:
{% extends "base.html"%}
{% block content %} <!--具體內(nèi)容-->
<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")
代碼有點啰嗦炕舵,不漂亮栋荸,但基本意圖能表達(dá)清楚菇怀,功能也可以實現(xiàn),但現(xiàn)在的問題來了晌块,加入我新增一個字段爱沟,那么需要修改三處代碼(html,form.get,校驗)匆背,并且尤其是需要修改html呼伸,而且html部分沒有驗證,如果增加客戶端驗證的話钝尸,需要修改的會更多括享。那么有沒有一個針對表單進(jìn)行優(yōu)化的工具呢,答案是當(dāng)然有珍促,輪到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
下面創(chuàng)建一個表單RegisterForm:
class RegisterForm(Form):
username = StringField("請輸入用戶名", validators=[DataRequired()])
password = PasswordField("請輸入密碼", validators=[DataRequired()])
repassword=PasswordField("確認(rèn)密碼", 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 %} <!--具體內(nèi)容-->
{% import "bootstrap/wtf.html" as wtf %} <!--導(dǎo)入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)}} <!--創(chuàng)建表單-->
</div>
</div>
</div>
{% endblock %}
執(zhí)行澳叉,輸出結(jié)果:
阿歐隙咸,報錯了,看看輸出是什么錯誤:
注意紅線一句成洗,是CSRF錯誤五督,CSRF的概念可直接百度,知道問題了,其實也很好修改瓶殃,在框架中增加一個秘鑰就可以有效的防范了充包,在default.py中增加一行:
app.config['SECRET_KEY'] = "Niu_blog String"
秘鑰字符串可自定義
然后再次運行,出現(xiàn)界面:
并且包含驗證bootstrap的驗證樣式遥椿,接下來繼續(xù)改造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,然后點擊提交:
注意载慈,由于代碼中提交成功之后依然是返回到此頁惭等,并注入內(nèi)容,所以顯示沒有問題办铡,看看db中:
記錄正常進(jìn)入db辞做,功能實現(xiàn)完成。
改善登錄頁
下面改造登錄頁寡具,首先創(chuàng)建登錄表單:
class LoginForm(Form):
username=StringField("請輸入用戶名",validators=[DataRequired()])
password=PasswordField("請輸入密碼")
submit=SubmitField("登錄")
修改登錄模板頁:
{% extends "base.html"%}
{% import "bootstrap/wtf.html" as wtf %}
{% block content %} <!--具體內(nèi)容-->
<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)
重啟服務(wù)凭豪,運行程序,輸入zhangji和123后晒杈,成功登錄首頁
回到首頁
現(xiàn)在首頁白茫茫的一片嫂伞,什么內(nèi)容都沒有,正常的輕博客應(yīng)該登錄后顯示發(fā)博按鈕拯钻,已關(guān)注文章等帖努,但首先要記錄登錄的狀態(tài),這些將在下一章說明粪般。