使用Python-Flask框架开发Web网站系列课程(五)用户管理

简介: 版权声明:如需转载,请注明转载地址。 https://blog.csdn.net/oJohnny123/article/details/82147331 前言使用IDE:PyCharm操作系统:MacPython的版本:3.6我的邮箱:51263921@qq.com交流群:372430835说明:本次课程的GitHub代码在最下面。
版权声明:如需转载,请注明转载地址。 https://blog.csdn.net/oJohnny123/article/details/82147331

前言


使用IDE:PyCharm

操作系统:Mac

Python的版本:3.6

我的邮箱:51263921@qq.com

交流群:372430835

说明:

本次课程的GitHub代码在最下面。

本次课程基于上个课程的代码,如果没看过的请先传送:

使用Python的瓶框架开发的Web网站系列课程(一)构建项目

使用Python的瓶框架开发的Web网站系列课程(二)注册功能

使用Python-Flask框架开发Web网站系列课程(三)登录功能

使用Python-Flask框架开发Web网站系列课程(四)构建前端

用户管理


用户管理,简单的来说,包含用户的增、删、改、查。还有用户角色,例如你是普通用户呢,还是管理员。增加用户我们已经在一开始的课程完成了,就是注册功能。本次课程我们将使用datatables控件来制作表格(table),用于展示多个用户的信息。

按照我实际工作中的习惯,我们先将页面大致创建好,再做内容的渲染。

1.1  创建前端页面。

1.1.1  修改一下上次课程的页面,增加 flask  的 flash消息功能。

全路径: /myproject/frontend/base/_navbar.html

新增的代码在最下面。

<div class="row border-bottom">
    <nav class="navbar navbar-static-top white-bg" role="navigation" style="margin-bottom: 0">
        <div class="navbar-header">
            <a class="navbar-minimalize minimalize-styl-2 btn btn-primary " href="#"><i class="fa fa-bars"></i> </a>
            <form role="search" class="navbar-form-custom" action="" method="post">
                <div class="form-group">
                    <input type="text" placeholder="Search for something..." class="form-control" name="top-search" id="top-search">
                </div>
            </form>
        </div>
        <ul class="nav navbar-top-links navbar-right">
            {% if current_user.is_authenticated %}
                <li>
                    <span class="m-r-sm text-muted welcome-message">欢迎使用myproject,{{current_user.username}}</span>
                </li>

                <li>
                    <a href="/account/logout">
                        <i class="fa fa-sign-out"></i> Log out
                    </a>
                </li>
            {% else %}

                <li>
                     <a href="/account/login">
                        <i class="fa fa-sign-out"></i> 请登录
                    </a>
                </li>

            {% endif %}
        </ul>
    </nav>
</div>
{% with messages = get_flashed_messages() %}
  {% if messages %}
    {% for message in messages %}
      <div class="alert alert-success">
          {{ message }}
           <button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
      </div>
    {% endfor %}
  {% endif %}
{% endwith %}

1.1.2  修改_head.html增加 datatable的css和js

下载https://github.com/lyy8510a/myproject/blob/master/frontend/static/css/plugins/dataTables/datatables.min.css 放到

全路径: /myproject/frontend/static/css/plugins/dataTables/datatables.min.css

下载https://github.com/lyy8510a/myproject/blob/master/frontend/static/js/plugins/dataTables/datatables.min.js 放到

全路径: /myproject/frontend/static/js/plugins/dataTables/datatables.min.js

<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.css" rel="stylesheet">
<link href="https://cdn.bootcss.com/font-awesome/4.3.0/css/font-awesome.css" rel="stylesheet">
<link href="https://cdn.bootcss.com/animate.css/3.5.2/animate.css" rel="stylesheet">
<link href="{{STATIC_URL}}/css/style.css" rel="stylesheet">
<link href="https://cdn.bootcss.com/metisMenu/2.0.2/metisMenu.css" rel="stylesheet">




<!-- Mainly scripts -->
<script src="https://cdn.bootcss.com/jquery/2.1.1/jquery.js"></script>
<script src="https://cdn.bootcss.com/bootstrap/3.3.6/js/bootstrap.js"></script>
<script src="https://cdn.bootcss.com/jqueryui/1.10.4/jquery-ui.js"></script>
<script src="https://cdn.bootcss.com/metisMenu/2.0.2/metisMenu.js"></script>
<script src="https://cdn.bootcss.com/jQuery-slimScroll/1.3.6/jquery.slimscroll.js"></script>
<script src="https://cdn.bootcss.com/pace/1.0.2/pace.js"></script>
<script src="{{STATIC_URL}}/js/inspinia.js"></script>


<!--datatables-->
<link href="{{STATIC_URL}}/css/plugins/dataTables/datatables.min.css" rel="stylesheet">
<script src="{{STATIC_URL}}/js/plugins/datatables/datatables.min.js" ></script>

1.1.3 新增users.html

本页面就是用户清单的页面啦,有个小逻辑就是如果是管理员,可以看全部用户,如果是普通用户,只能看到自己的,而且只能修改密码。不能删除和编辑用户。

全路径: /myproject/frontend/account/users.html 

<!--第四课内容 -->
{% extends 'base/layout.html' %}

<!--第四课内容 下面是正文-->
{% block content %}
    <div class="wrapper wrapper-content">
        <div class="row">
            <div class="col-lg-12">
                <div class="ibox float-e-margins">
                    <div class="ibox-title">
                        <h5>{{tag}}</h5>
                    </div>
                    <div class="ibox-content">
                        <div class="row">

                            <div class="table-responsive">
                                <table class="table table-striped table-bordered table-hover dataTables-example">
                                  <thead>
                                     <tr>
                                        <th>ID</th>
                                        <th>用户名</th>
                                        <th>Email</th>
                                        <th>角色</th>
                                        <th>操作</th>
                                     </tr>
                                  </thead>
                                  <tbody>
                                      {% if current_user.role_id == 2 %}
                                          {% for user in users %}
                                                <tr>
                                                    <td>{{user.id}}</td>
                                                    <td>{{user.username}}</td>
                                                    <td>{{user.email}}</td>
                                                    <td>{{user.role.name}}</td>
                                                    <td><a href="">修改密码</a> | <a href="/account/edituser?id={{user.id}}">编辑</a> | <a href="/account/deluser?id={{user.id}}">删除</a></td>
                                                </tr>
                                          {% endfor %}
                                      {% else %}
                                          {% for user in users %}
                                                {% if user.id == current_user.id %}
                                                    <tr>
                                                        <td>{{user.id}}</td>
                                                        <td>{{user.username}}</td>
                                                        <td>{{user.email}}</td>
                                                        <td>{{user.role.name}}</td>
                                                        <td><a href="">修改密码</a></td>
                                                    </tr>
                                                {% endif %}
                                          {% endfor %}
                                      {% endif %}
                                  </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

<script>
    $(document).ready(function() {
          $('.dataTables-example').DataTable({
                dom: '<"html5buttons"B>lTfgitp',
                buttons: [
                    { extend: 'copy'},
                    {extend: 'csv'},
                    {extend: 'excel', title: 'ExampleFile'},
                    {extend: 'pdf', title: 'ExampleFile'},

                    {extend: 'print',
                     customize: function (win){
                            $(win.document.body).addClass('white-bg');
                            $(win.document.body).css('font-size', '10px');

                            $(win.document.body).find('table')
                                    .addClass('compact')
                                    .css('font-size', 'inherit');
                    }
                    }
                ]
            });
    })


</script>


{% endblock %}


1.1.4 新增edituser.html 

编辑用户信息的页面

全路径: /myproject/frontend/account/edituser.html 

{% extends 'base/layout.html'  %}
{% block content %}


<div class="wrapper wrapper-content">
    <div class="container-fluid">
        <div class="row">
            <div class="col-lg-12">
                <div class="ibox float-e-margins">
                    <div class="ibox-title">
                        <h5>编辑用户信息</h5>

                    </div>
                    <div class="ibox-content">
                        <form action="/account/edituser" class="form-horizontal" enctype="multipart/form-data"  method="post" >

                             <input type="hidden" name="id" value="{{ user_info.id }}">
                             <div class="form-group">
                                <label class="col-lg-2 control-label">id:</label>
                                <div class="col-lg-6"><input type="text"  name="id" class="form-control" value="{{ user_info.id }}" disabled></div>
                             </div>
                             <div class="hr-line-dashed" ></div>
                             <div class="form-group">
                                <label class="col-lg-2 control-label">用户名:</label>
                                <div class="col-lg-6"><input type="text"  name="username" class="form-control" value="{{ user_info.username }}" disabled></div>
                             </div>
                             <div class="hr-line-dashed" ></div>
                             <div class="form-group">
                                <label class="col-lg-2 control-label">EMAIL:</label>
                                <div class="col-lg-6"><input type="text"  name="email" class="form-control" value="{{ user_info.email }}" ></div>
                             </div>
                            <div class="hr-line-dashed" ></div>
                            <div class="form-group">
                                <label class="col-lg-2 control-label">角色:</label>
                                <div class="col-lg-6">
                                    <select name="role_id" class="form-control">
                                        {%  if user_info.role_id %}
                                            <option value="{{user_info.role_id}}">{% if user_info.role_id ==1 %}普通用户{% else %}管理员{% endif %}</option>
                                            <option value="1">普通用户</option>
                                            <option value="2">管理员</option>
                                        {% else %}
                                            <option value="">请选择</option>
                                            <option value="1">普通用户</option>
                                            <option value="2">管理员</option>
                                        {% endif %}
                                    </select>
                                </div>
                             </div>
                            <div class="hr-line-dashed" ></div>
                             <div class="form-group">
                                 <div class="col-lg-2">
                                 </div>
                                 <div class="col-lg-4">
                                    <button type="submit" class="btn btn-primary" >保存</button>
                                 </div>
                             </div>
                        </form>
                    </div>
                </div>
            </div>

        </div>
    </div>
</div>


{% endblock %}

1.2 后端的逻辑代码

1.2.1 修改原先/myproject/backend/account/views.py的代码

增加了修改用户、删除用户、角色model的代码

#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
Created by liaoyangyang1 on 2018/8/22 上午9:40.
"""
from flask import Blueprint,request,render_template,jsonify,flash  #第二课增加内容
from flask import redirect,url_for,abort #第五课新增
from backend.models.UserModel import User,Role #第五课新增
from backend.models import db
from flask_login import login_user,login_required,logout_user,current_user #第三课增加内容 #第五课新增
from functools import wraps #第五课新增
from backend.models.UserModel import Permission #第五课新增
from utils.layout import layout

#账户的蓝图  访问http://host:port/account 这个链接的子链接,都会跳到这里
account = Blueprint('account', __name__)  #第二课增加内容


def permission_required(permission): #第五课新增
    """Restrict a view to users with the given permission."""
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            if not current_user.can(permission):
                abort(403)
            return f(*args, **kwargs)
        return decorated_function
    return decorator


# 要求管理员权限
def admin_required(f): #第五课新增
    return permission_required(Permission.ADMINISTER)(f)

# 访问http://host:port/account/register 这个链接,就会跳到这里
@account.route('/register',methods=(["GET","POST"]))  #第二课增加内容
#上面的链接,绑定的就是这个方法,我们给浏览器或者接口请求 一个json格式的返回
def register():  #第二课增加内容
    if request.method == 'POST':
        try:
            form = request.form
            user = User(username=form['username'],email=form['email'],password=form['password'])
            db.session.add(user)
            db.session.commit()
            return redirect(url_for(request.args.get('next') or 'account.login'))
        except Exception as e:
            abort(403)
    return render_template('/account/register.html')

@account.route('/login',methods=(["GET","POST"]))
def login(): #第三课内容
    if request.method == "POST":
        form = request.form #获取登录表单
        user = User.query.filter_by(username=form['username']).first()  #查出用户信息
        if user is not None and user.password_hash is not None and user.verify_password(form['password']):  #检查密码是否正确
            login_user(user,True)  #登录操作
            flash('You are now logged in. Welcome back!', 'success')
            return redirect( url_for(request.args.get('next') or 'admin.index'))
        else:
            flash('Invalid email or password.', 'error')
    return render_template('/account/login.html')

@account.route('/logout')
@login_required
def logout():
    logout_user()
    flash('You have been logged out.', 'info')
    return redirect(url_for('admin.index'))


@account.route('/users')
@login_required
def user_list(): #第五课新增
    Role.insert_roles()
    user_list = User.query.outerjoin(Role, User.role_id == Role.id).all()
    return layout('/account/users.html',users=user_list)


@account.route('/edituser',methods=(["GET","POST"]))
@login_required
@admin_required
def user_edit(): #第五课新增
    if request.method == 'POST':
        try:
            form = request.form
            use_info = User.query.filter(User.id == form['id']).first()
            use_info.email = form['email']
            use_info.role_id = form['role_id']
            db.session.commit()
            flash('修改用户信息成功!', 'success')
        except Exception as e:
            print(e)
            flash('修改用户信息失败!', 'error')
        return redirect(url_for(request.args.get('next') or 'account.user_list'))

    id = request.values.get('id')
    user_info = User.query.filter_by(id=id).first()
    return layout('/account/edituser.html', user_info=user_info)

@account.route('/deluser')
@login_required
@admin_required
def user_del(): #第五课新增
    try:
        id = request.values.get('id')
        user = User.query.filter(User.id == id).first()
        db.session.delete(user)
        db.session.commit()
        flash('删除用户成功!', 'success')
    except Exception as e:
        print(e)
        flash('删除用户失败!', 'error')

    return redirect(url_for(request.args.get('next') or 'account.user_list'))


1.2.2 修改原先/myproject/backend/models/UserModel.py的代码

增加了角色方面的代码

#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
Created by liaoyangyang1 on 2018/8/22 下午1:50.
"""
from flask_login import UserMixin,AnonymousUserMixin  #第二课增加内容
from werkzeug.security import check_password_hash, generate_password_hash  #第二课增加内容
from backend.models import db  #第二课增加内容
from backend.views import login_manager #第三课新增
from flask import current_app #第五课内容


class Permission: #第五课内容
    GENERAL = 0x01
    ADMINISTER = 0xff

class Role(db.Model): #第五课内容
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    index = db.Column(db.String(64))
    default = db.Column(db.Boolean, default=False, index=True)
    permissions = db.Column(db.Integer)
    users = db.relationship('User', backref='role', lazy='dynamic')

    @staticmethod
    def insert_roles():
        roles = {
            'User': (Permission.GENERAL, 'main', True),
            'Administrator': (
                Permission.ADMINISTER,
                'admin',
                False  # grants all permissions
            )
        }
        for r in roles:
            role = Role.query.filter_by(name=r).first()
            if role is None:
                role = Role(name=r)
            role.permissions = roles[r][0]
            role.index = roles[r][1]
            role.default = roles[r][2]
            db.session.add(role)
        db.session.commit()

    def __repr__(self):
        return '<Role \'%s\'>' % self.name



class User(UserMixin, db.Model):  #第二课增加内容
    __tablename__ = 'users'  #这是我们将来建出来的表的表名,在这里定义,下面的都是字段名和字段类型长度这些
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True)
    email = db.Column(db.String(64), unique=True, index=True)
    password_hash = db.Column(db.String(128))
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))  #第五课内容

    def __init__(self, **kwargs): #第五课内容
        super(User, self).__init__(**kwargs)
        print(self)
        if self.role is None:
            if self.username == current_app.config['ADMIN_USER'] or self.email == current_app.config['ADMIN_EMAIL']:
                self.role = Role.query.filter_by(
                    permissions=Permission.ADMINISTER).first()
            if self.role is None:
                self.role = Role.query.filter_by(default=True).first()

    def can(self, permissions): #第五课内容
        return self.role is not None and \
            (self.role.permissions & permissions) == permissions

    def is_admin(self): #第五课内容
        return self.can(Permission.ADMINISTER)


    #脱敏
    @property
    def password(self):  #第二课增加内容
        raise AttributeError('`password` is not a readable attribute')
    #加密
    @password.setter
    def password(self, password):  #第二课增加内容
        self.password_hash = generate_password_hash(password)
    #校验密码
    def verify_password(self, password):  #第二课增加内容
        return check_password_hash(self.password_hash, password)
    #查询返回的格式
    def __repr__(self):  #第二课增加内容
        return '<User \'%s\'>' % self.username

class AnonymousUser(AnonymousUserMixin): #第三课新增
    def can(self, _):
        return False

    def is_admin(self):
        return False


login_manager.anonymous_user = AnonymousUser   #第三课新增


@login_manager.user_loader
def load_user(user_id): #第三课新增
    return User.query.get(int(user_id))

1.2.3 给自己的账号先设置为管理员

先在role表里面看管理员的id是多少,然后去user表将自己账号的role_id改成管理员角色的id

 

1.3 测试一下

管理员登录下:

编辑用户: 

修改用户角色成功 

 删除用户成功 

普通用户登录 

课程代码 


github地址:https://github.com/lyy8510a/myproject/releases/tag/v5

目录
相关文章
|
2月前
|
存储 Java 数据处理
(numpy)Python做数据处理必备框架!(一):认识numpy;从概念层面开始学习ndarray数组:形状、数组转置、数值范围、矩阵...
Numpy是什么? numpy是Python中科学计算的基础包。 它是一个Python库,提供多维数组对象、各种派生对象(例如掩码数组和矩阵)以及用于对数组进行快速操作的各种方法,包括数学、逻辑、形状操作、排序、选择、I/0 、离散傅里叶变换、基本线性代数、基本统计运算、随机模拟等等。 Numpy能做什么? numpy的部分功能如下: ndarray,一个具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组 用于对整组数据进行快速运算的标准数学函数(无需编写循环)。 用于读写磁盘数据的工具以及用于操作内存映射文件的工具。 线性代数、随机数生成以及傅里叶变换功能。 用于集成由C、C++
305 0
|
2月前
|
Java 数据处理 索引
(Pandas)Python做数据处理必选框架之一!(二):附带案例分析;刨析DataFrame结构和其属性;学会访问具体元素;判断元素是否存在;元素求和、求标准值、方差、去重、删除、排序...
DataFrame结构 每一列都属于Series类型,不同列之间数据类型可以不一样,但同一列的值类型必须一致。 DataFrame拥有一个总的 idx记录列,该列记录了每一行的索引 在DataFrame中,若列之间的元素个数不匹配,且使用Series填充时,在DataFrame里空值会显示为NaN;当列之间元素个数不匹配,并且不使用Series填充,会报错。在指定了index 属性显示情况下,会按照index的位置进行排序,默认是 [0,1,2,3,...] 从0索引开始正序排序行。
232 0
|
2月前
|
Java 数据挖掘 数据处理
(Pandas)Python做数据处理必选框架之一!(一):介绍Pandas中的两个数据结构;刨析Series:如何访问数据;数据去重、取众数、总和、标准差、方差、平均值等;判断缺失值、获取索引...
Pandas 是一个开源的数据分析和数据处理库,它是基于 Python 编程语言的。 Pandas 提供了易于使用的数据结构和数据分析工具,特别适用于处理结构化数据,如表格型数据(类似于Excel表格)。 Pandas 是数据科学和分析领域中常用的工具之一,它使得用户能够轻松地从各种数据源中导入数据,并对数据进行高效的操作和分析。 Pandas 主要引入了两种新的数据结构:Series 和 DataFrame。
381 0
|
2月前
|
Java 数据处理 索引
(numpy)Python做数据处理必备框架!(二):ndarray切片的使用与运算;常见的ndarray函数:平方根、正余弦、自然对数、指数、幂等运算;统计函数:方差、均值、极差;比较函数...
ndarray切片 索引从0开始 索引/切片类型 描述/用法 基本索引 通过整数索引直接访问元素。 行/列切片 使用冒号:切片语法选择行或列的子集 连续切片 从起始索引到结束索引按步长切片 使用slice函数 通过slice(start,stop,strp)定义切片规则 布尔索引 通过布尔条件筛选满足条件的元素。支持逻辑运算符 &、|。
157 0
|
2月前
|
开发框架 前端开发 Go
【GoGin】(0)基于Go的WEB开发框架,GO Gin是什么?怎么启动?本文给你答案
Gin:Go语言编写的Web框架,以更好的性能实现类似Martini框架的APInet/http、Beego:开源的高性能Go语言Web框架、Iris:最快的Go语言Web框架,完备的MVC支持。
351 1
|
3月前
|
机器学习/深度学习 算法 PyTorch
【DQN实现避障控制】使用Pytorch框架搭建神经网络,基于DQN算法、优先级采样的DQN算法、DQN + 人工势场实现避障控制研究(Matlab、Python实现)
【DQN实现避障控制】使用Pytorch框架搭建神经网络,基于DQN算法、优先级采样的DQN算法、DQN + 人工势场实现避障控制研究(Matlab、Python实现)
146 0
|
11月前
|
安全 前端开发 数据库
Python 语言结合 Flask 框架来实现一个基础的代购商品管理、用户下单等功能的简易系统
这是一个使用 Python 和 Flask 框架实现的简易代购系统示例,涵盖商品管理、用户注册登录、订单创建及查看等功能。通过 SQLAlchemy 进行数据库操作,支持添加商品、展示详情、库存管理等。用户可注册登录并下单,系统会检查库存并记录订单。此代码仅为参考,实际应用需进一步完善,如增强安全性、集成支付接口、优化界面等。
|
搜索推荐 数据可视化 数据挖掘
基于Python flask框架的招聘数据分析推荐系统,有数据推荐和可视化功能
本文介绍了一个基于Python Flask框架的招聘数据分析推荐系统,该系统具备用户登录注册、数据库连接查询、首页推荐、职位与城市分析、公司性质分析、职位需求分析、用户信息管理以及数据可视化等功能,旨在提高求职者的就业效率和满意度,同时为企业提供人才匹配和招聘效果评估手段。
607 0
基于Python flask框架的招聘数据分析推荐系统,有数据推荐和可视化功能
|
关系型数据库 MySQL 数据库
如何使用Python的Flask框架来构建一个简单的Web应用
如何使用Python的Flask框架来构建一个简单的Web应用
281 0
|
前端开发 安全 JavaScript
Python的Flask框架的学习笔记(前后端变量传送,文件上传,网页返回)内含实战:实现一个简单的登录页面
Python的Flask框架的学习笔记(前后端变量传送,文件上传,网页返回)内含实战:实现一个简单的登录页面
540 0

推荐镜像

更多