关于博主
努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!
微信公众号: 啃饼思录
QQ: 2810706745(啃饼小白)
写在前面
从本篇笔记开始,我们将介绍前台的配置,也就是说现在你所有关于后台的页面都是可以关闭的,只需保留manage.py和moleds.py即可,好了话不多说,我们开始本篇的学习吧!
本篇笔记对应上传的仓库为:https://github.com/licheetools/movie对应第十三篇。
前台会员管理
前台会员管理主要包括会员注册,会员登录,会员退出,修改会员资料(包括会员密码),会员登录日志等5个功能,下面分别介绍。
会员注册
使用到的内容
我们将使用到的内容有:
模型:User
表单: RegisterForm
请求方法: GET ,POST
访问控制: 无
1、添加表单验证字段
打开home/forms.py,我们定义Form字段,注意因为是会员注册,所以对应的html页面就是register.html,而且我们在forms.py里面定义的字段必须与register.html里面的保持一致!(如果觉得不是很容易看出来,可以运行项目,直接访问register.html页面,这样明显多了!),可以复制修改后台的代码验证字段:
#!/user/bin/python
# -*- coding:utf-8 -*-
# @Time: 2018/8/29 21:17
# @Author: Envse
# @File: forms.py
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, FileField, TextAreaField, SelectField, SelectMultipleField
from wtforms.validators import DataRequired, ValidationError, EqualTo, Email, Regexp
from app.models import User
# 前台会员注册
class RegisterForm(FlaskForm):
name = StringField(
label="昵称",
validators=[
DataRequired("昵称不能为空!")
],
description="昵称",
render_kw={
"class": "form-control input-lg",
"placeholder": "请输入昵称!",
# "required": "required" # 注释此处显示forms报错errors信息
}
)
email = StringField(
label="邮箱",
validators=[
DataRequired("邮箱不能为空!"),
Email("邮箱格式不正确!")
],
description="邮箱",
render_kw={
"class": "form-control input-lg",
"placeholder": "请输入邮箱!",
# "required": "required" # 注释此处显示forms报错errors信息
}
)
phone = StringField(
label="手机号码",
validators=[
DataRequired("手机号码不能为空!"),
Regexp("1[3458]\\d{9}", message="手机格式不正确!")
],
description="手机号码",
render_kw={
"class": "form-control input-lg", # 注意这个和后端页面的区别,不要拷贝错误
"placeholder": "请输入手机号码!",
# "required": "required" # 注释此处显示forms报错errors信息
}
)
pwd = PasswordField(
label="密码",
validators=[
DataRequired("密码不能为空!")
],
description="密码",
render_kw={
"class": "form-control input-lg",
"placeholder": "请输入密码!",
# "required": "required" # 注释此处显示forms报错errors信息
}
)
repwd = PasswordField(
label="确认密码",
validators=[
DataRequired("确认密码不能为空!"),
EqualTo('pwd', message="两次密码不一致!")
],
description="确认密码",
render_kw={
"class": "form-control input-lg",
"placeholder": "请输入确认密码!",
# "required": "required" # 注释此处显示forms报错errors信息
}
)
submit = SubmitField(
'注册',
render_kw={
"class": "btn btn-lg btn-success btn-block",
}
)
def validate_name(self, field):
name = field.data
user = User.query.filter_by(name=name).count()
if user == 1:
raise ValidationError("该昵称已经存在!")
def validate_email(self, field):
email = field.data
user = User.query.filter_by(email=email).count()
if user == 1:
raise ValidationError("该邮箱已经存在!")
def validate_phone(self, field):
phone = field.data
user = User.query.filter_by(phone=phone).count()
if user == 1:
raise ValidationError("该手机号已经存在!")
2、准备页面渲染字段
打开home/views.py文件,我们修改register函数:
from app.home.forms import RegisterForm
from app.models import User
# 会员注册
@home.route('/register/')
def register():
form = RegisterForm()
if form.validate_on_submit():
data = form.data
return render_template("home/register.html", form=form)
3、后台页面传值显示以及操作信息提示
可以仿照后台的那些页面的配置来修改register.html:
记得在submit的上面添加{{ form.csrf_token }},还有form提交的方法:
<form role="form" method="post" >
4、后台页面错误信息提示
打开register.html页面,我们同样可以仿照auth_add.html来进行修改:(里面的phone需要按照我们数据库里字段的要求进行修改)
{% for err in form.phone.errors %}
<div class="col-md-12" id="error_phone">{{ err }}</div>
{% endfor %}
5、修改会员注册函数
from app.models import User
from werkzeug.security import generate_password_hash
import uuid
from app import db
from flask import flash
# 会员注册
@home.route('/register/', methods=["GET", "POST"])
def register():
form = RegisterForm()
if form.validate_on_submit():
data = form.data
user = User(
name=data["name"],
email=data["email"],
phone=data["phone"],
pwd=generate_password_hash(data["pwd"]),
uuid=uuid.uuid4().hex
)
db.session.add(user)
db.session.commit()
flash("恭喜你注册成功,赶紧登录吧!", "ok")
return redirect(url_for("home.login"))
return render_template("home/register.html", form=form)
6、数据库字段验证
打开models.py文件,我们在User函数里面新增以下代码:
def check_pwd(self, pwd):
from werkzeug.security import check_password_hash
return check_password_hash(self.pwd, pwd)
然后运行一下我们的manage.py文件,就可以去首页注册我们的会员了!
会员登录
使用到的内容
我们将使用到的内容有:
模型:User
表单: LoginForm
请求方法: GET ,POST
访问控制: 无
1、添加表单验证字段
打开home/forms.py,我们定义Form验证字段:
# 前台会员登录
class LoginForm(FlaskForm):
name = StringField(
label="账号",
validators=[
DataRequired("账号不能为空!")
],
description="账号",
render_kw={
"class": "form-control input-lg",
"placeholder": "请输入账号!",
# "required": "required" # 注释此处显示forms报错errors信息
}
)
pwd = PasswordField(
label="密码",
validators=[
DataRequired("密码不能为空!")
],
description="密码",
render_kw={
"class": "form-control input-lg",
"placeholder": "请输入密码!",
# "required": "required" # 注释此处显示forms报错errors信息
}
)
submit = SubmitField(
'登录',
render_kw={
"class": "btn btn-lg btn-primary btn-block", #注意这里最好是primary,不要用success
}
)
2、准备页面渲染字段
打开admin/views.py文件,我们修改login函数:
from app.home.forms import LoginForm
# 登入
@home.route('/login/', methods=["GET", "POST"])
def login():
form = LoginForm()
if form.validate_on_submit():
data=form.data
return render_template("home/login.html", form=form)
3、后台页面传值显示以及操作信息提示
可以仿照后台的那些页面的配置来修改login.html:
记得在submit的上面添加{{ form.csrf_token }},还有form提交的方法:
<form role="form" method="post" >
4、后台页面错误信息提示
打开login.html页面,我们同样可以仿照auth_add.html来进行修改:(里面的title需要按照我们数据库里字段的要求进行修改)
{% for err in form.title.errors %}
<div class="col-md-12">
<p style="color:red">{{ err }}</p>
</div>
{% endfor %}
5、修改登录函数:
# 登入
@home.route('/login/', methods=["GET", "POST"])
def login():
form = LoginForm()
if form.validate_on_submit():
data=form.data
user = User.query.filter_by(name=data["name"]).first()
if not user.check_pwd(data["pwd"]):
flash("密码错误!", "err")
return redirect(url_for("home.login"))
session["user"] = user.name
session["user_id"] = user.id
userlog = UserLog(
user_id=user.id,
ip=request.remote_addr
)
db.session.add(userlog)
db.session.commit()
return redirect(url_for("home.user"))
return render_template("home/login.html", form=form)
然后运行一下我们的manage.py文件,就可以去首页登录我们的网站了!
思考问题
现在有这样的问题,就是假如我们的账号不存在(这种情况也是有的,你长时间没登录忘记账号和密码了,然后就随便输入),这时候就很容易出现下面的错误:
if not user.check_pwd(data["pwd"]):
AttributeError: 'NoneType' object has no attribute 'check_pwd'
所以我们可以添加账号的验证(没有必要进行密码的验证,因为账号都不存在,哪来的密码呢,哈哈哈哈哈哈哈哈),可以仿照之前的注册在loginForm中定义:
def validate_name(self, field):
name = field.data
user = User.query.filter_by(name=name).count()
if user == 0:
raise ValidationError("该账号不存在!")
会员登出
会员登出相比其他是非常简单的,只需要把session里面的user和user_id删除即可:
# 登出
@home.route('/logout/')
def logout():
session.pop("user", None) # 重定向到前台的登录页面
session.pop("user_id", None)
return redirect(url_for('home.login'))
既然登出了,就不能查看登入之后的信息了,我们可以采用登入装饰器来控制访问,可以复制我们之前在admin里面配置的那个就可以:
from functools import wraps
# 登录装饰器
def user_login_req(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if "user" not in session:
return redirect(url_for("home.login", next=request.url))
return f(*args, **kwargs)
return decorated_function
然后就要在这些页面添加控制访问的权限了:
接下来就是会员中心资料的修改了!
会员中心资料修改
使用到的内容
我们将使用到的内容有:
模型:User
表单: UserdetailForm
请求方法: GET ,POST
访问控制: @user_login_req
1、添加表单验证字段
# 修改个人资料
class UserdetailForm(FlaskForm):
name = StringField(
label="昵称",
validators=[
DataRequired("昵称不能为空!")
],
description="昵称",
render_kw={
"class": "form-control input-lg",
"placeholder": "请输入昵称!",
# "required": "required" # 注释此处显示forms报错errors信息
}
)
email = StringField(
label="邮箱",
validators=[
DataRequired("邮箱不能为空!"),
Email("邮箱格式不正确!")
],
description="邮箱",
render_kw={
"class": "form-control input-lg",
"placeholder": "请输入邮箱!",
# "required": "required" # 注释此处显示forms报错errors信息
}
)
phone = StringField(
label="手机号码",
validators=[
DataRequired("手机号码不能为空!"),
Regexp("1[3458]\\d{9}", message="手机格式不正确!")
],
description="手机号码",
render_kw={
"class": "form-control input-lg",
"placeholder": "请输入手机号码!",
# "required": "required" # 注释此处显示forms报错errors信息
}
)
face = FileField(
label="头像",
validators=[
DataRequired("请上传头像!")
],
description="头像",
)
info = TextAreaField(
label="简介",
validators=[
DataRequired("简介不能为空")
],
description="简介",
render_kw={
"class": "form-control",
"rows=": 10,
}
)
submit = SubmitField(
'保存修改',
render_kw={
"class": "btn btn-success",
}
)
2、准备页面渲染字段
打开admin/views.py文件,我们修改user函数:
from app.home.forms import UserdetailForm
from werkzeug.utils import secure_filename
import os
import datetime
from datetime import datetime
# 会员中心
@home.route('/user/', methods=["GET", "POST"])
@user_login_req
def user():
form = UserdetailForm()
user = User.query.get(int(session["user_id"]))
form.face.validators = []
if request.method == "GET": # 给它们赋初始值
form.name.data = user.name
form.email.data = user.email
form.phone.data = user.phone
form.info.data = user.info
if form.validate_on_submit():
data = form.data
if form.face.data != "": # 没有修改时不能报错
file_face = secure_filename(form.face.data.filename)
if not os.path.exists(app.config["FC_DIR"]):
os.makedirs(app.config["FC_DIR"])
os.chmod(app.config["FC_DIR"])
user.face = change_filename(file_face)
form.face.data.save(app.config["FC_DIR"] + user.face)
name_count = User.query.filter_by(name=data["name"]).count()
if data["name"] != user.name and name_count == 1:
flash("该昵称已经存在!", "err")
return redirect(url_for("home.user"))
email_count = User.query.filter_by(email=data["email"]).count()
if data["email"] != user.email and email_count == 1:
flash("该邮箱已经存在!", "err")
return redirect(url_for("home.user"))
phone_count = User.query.filter_by(phone=data["phone"]).count()
if data["phone"] != user.phone and phone_count == 1:
flash("该手机已经存在!", "err")
return redirect(url_for("home.user"))
user.name = data["name"]
user.email = data["email"]
user.phone = data["phone"]
user.info = data["info"]
db.session.add(user)
db.session.commit()
flash("修改成功!", "ok")
return redirect(url_for("home.user"))
return render_template("home/user.html", form=form, user=user)
3、在初始的--init--.py文件里面,新增我们的图片存储地址:
app.config["FC_DIR"] = os.path.join(os.path.abspath(os.path.dirname(__file__)), "static/uploads/users/")
4、后台页面传值显示以及操作信息提示
可以仿照前面的auth_add.html来修改user.html:
记得在submit的上面添加{{ form.csrf_token }},还有form提交的方法以及图片上传类型:
<form role="form" method="post" enctype="multipart/form-data">
5、前台页面错误信息提示
打开user.html页面,我们同样可以仿照auth_add.html来进行修改:(里面的title需要按照我们数据库里字段的要求进行修改)
{% for err in form.title.errors %}
<div class="col-md-12">
<p style="color:red">{{ err }}</p>
</div>
{% endfor %}
6、设置头像默认值
打开user.html页面,我们给用户头像一个初始值:
然后运行一下我们的manage.py文件,就可以去后台修改个人中心的信息了!
修改密码
使用到的内容
我们将使用到的内容有:
模型:User
表单: PwdForm
请求方法: GET ,POST
访问控制: @user_login_req
1、添加表单验证字段
这个表单验证字段和我们后台定义的修改密码是一模一样的,所以我们完全可以复制粘贴之前的代码:
# 修改密码
class PwdForm(FlaskForm):
old_pwd = PasswordField(
label="旧密码",
validators=[
DataRequired("旧密码不能为空!")
],
description="旧密码",
render_kw={
"class": "form-control",
"placeholder": "请输入旧密码!",
# "required": "required" # 注释此处显示forms报错errors信息
}
)
new_pwd = PasswordField(
label="新密码",
validators=[
DataRequired("新密码不能为空!")
],
description="新密码",
render_kw={
"class": "form-control",
"placeholder": "请输入新密码!",
# "required": "required" # 注释此处显示forms报错errors信息
}
)
submit = SubmitField(
'修改密码',
render_kw={
"class": "btn btn-success",
}
)
2、准备页面渲染字段
打开admin/views.py文件,我们修改pwd函数(这个和我们后台修改密码一样,复制修改一下即可):
from app.home.forms import PwdForm
# 修改密码
@home.route('/pwd/', methods=["GET", "POST"])
@user_login_req
def pwd():
form = PwdForm()
if form.validate_on_submit(): # 表单验证,没有这个则无法进行错误信息提示
data = form.data
user = User.query.filter_by(name=session["user"]).first()
user.pwd = generate_password_hash(data["new_pwd"])
db.session.add(user)
db.session.commit()
flash("修改密码成功,请重新登录!", "ok")
return redirect(url_for("home.logout"))
return render_template("home/pwd.html", form=form)
3、前台页面传值显示以及操作信息提示
可以仿照前面的auth_add.html来修改pwd.html:
记得在submit的上面添加{{ form.csrf_token }},还有form提交的方法:
<form role="form" method="post" >
4、前台页面错误信息提示
打开pwd.html页面,我们同样可以仿照auth_add.html来进行修改:(里面的title需要按照我们数据库里字段的要求进行修改)
{% for err in form.title.errors %}
<div class="col-md-12">
<p style="color:red">{{ err }}</p>
</div>
{% endfor %}
5、修改一下密码函数
# 修改密码
@home.route('/pwd/', methods=["GET", "POST"])
@user_login_req
def pwd():
form = PwdForm()
if form.validate_on_submit(): # 表单验证,没有这个则无法进行错误信息提示
data = form.data
user = User.query.filter_by(name=session["user"]).first()
if not user.check_pwd(data["old_pwd"]):
flash("旧密码错误!", "err")
return redirect(url_for('home.pwd'))
if data["old_pwd"] == data["new_pwd"]:
flash("新旧密码不能一样!", "err")
return redirect(url_for('home.pwd'))
user.pwd = generate_password_hash(data["new_pwd"])
db.session.add(user)
db.session.commit()
flash("修改密码成功,请重新登录!", "ok")
return redirect(url_for("home.logout"))
return render_template("home/pwd.html", form=form)
然后运行一下我们的manage.py文件,就可以去个人中心修改密码了!鉴于评论现在配置过早,我们现在暂且不配置,转向对登入日志的配置!
登入日志
使用到的内容
我们将使用到的内容有:
模型:User
表单: 无
请求方法: GET
访问控制: @user_login_req
1、编写登入日志函数
这个是完全可以参考我们之前在后台对会员登录日志列表的配置:
# 登入日志
@home.route('/loginlog/<int:page>/', methods=["GET"])
@user_login_req
def loginlog(page=None):
if page is None:
page = 1
# 查询的时候关联标签,采用join来加进去,多表关联用filter,过滤用filter_by
page_data = UserLog.query.filter_by(
user_id=int(session["user_id"])
).order_by(
UserLog.addtime.desc()
).paginate(page=page, per_page=10)
return render_template("home/loginlog.html", page_data=page_data)
2、遍历所要信息
打开loginlog.html页面,我们进行配置:
{% for v in page_data.items %}
<tr>
<td>{{ v.id }}</td>
<td>{{ v.addtime }}</td>
<td>{{ v.ip }}</td>
</tr>
{% endfor %}
3、添加列表页
记得之前说过,凡是需要列表显示的都要有列表页page=1,打开menu.html,我们添加page=1即可!
4、分页显示
我们在ui文件夹下面新建一个名为home_page.html的页面,将之前的admin_page.html的代码拷贝进去,然后我们修改一下我们所指示的地方,增加nav标签,和修改class属性:
接着就是开头的引入:
{% import "ui/home_page.html" as pg %}
以及后面的替换:
<div class="box-footer clearfix">
{{ pg.page(page_data, "home.loginlog") }}
</div>
就是这个样子:
鉴于篇幅过长,后面的内容我们下一篇再介绍!
至此,本篇关于前台会员管理的介绍就到此为止了,感谢你的赏阅!!!
本篇笔记对应上传的仓库为:https://github.com/licheetools/movie对应第十三篇。















网友评论