美文网首页利用Flask搭建微电影视频网站
利用Flask搭建微电影视频网站(十三):前台会员管理

利用Flask搭建微电影视频网站(十三):前台会员管理

作者: 啃饼小白 | 来源:发表于2018-09-16 08:39 被阅读2次

关于博主

努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!

                  微信公众号:  啃饼思录
                   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里面的useruser_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对应第十三篇。

相关文章

网友评论

  • 领带衬有黄金:老哥,有这个视频吗,我的视频资源中间断了点
    啃饼小白:@领带衬有黄金 慕课网有这个课程,你可以去那里面购买一下,支持正版

本文标题:利用Flask搭建微电影视频网站(十三):前台会员管理

本文链接:https://www.haomeiwen.com/subject/dtqigftx.html