完整的flask项目

 
 

作者:李忠林

Github: https://github.com/Leezhonglin

Gitblog: https://leezhonglin.github.io/

日期: 2018-06-15

<原创>:学了一周的flask项目,在这里把我自己的做的项目分享给大家.实现了如下的功能.

项目内容:

1,班级管理
  1. 班级列表

  2. 班级增加

  3. 班级修改

  4. 查看班级中的学生

2,学生管理的增删改查
  1. 学生列表

  2. 学生添加

  3. 学生修改

    扫描二维码关注公众号,回复: 1830747 查看本文章
3,权限的增加
  1. 角色的增加

  2. 角色列表

    1. 查看用户权限

    2. 添加用户权限

    3. 减少用户权限

  3. 权限列表

  4. 添加权限

4,用户管理
  1. 用户列表

  2. 用户添加

  3. 用户角色分配

5,系统管理
  1. 修改密码

  2. 退出

  1. 用户登录注册

    1. 用户注册

    2. 用户登录验证

6,页面分页

详细的项目代码

在这里我就省略建立项目的流程直接来开始我们的项目.....

建立项目的流程不会可以自行百度flask官网

1.首先介绍一下项目的文件构成,如下图


2, 启动文件的配置
#manange.py文件的内容
from flask_script import Manager

from utils.functions import create_app

app = create_app()

manage = Manager(app=app)

if __name__ == '__main__':
    manage.run()
3,重要的配置
#utils中funtions.py文件中的类容,重要的配置
import os

import redis
from flask import Flask

from App.user_views import user_blueprint
from App.models import db


def create_app():
    # 定义系统路径的变量
    BASE_DIR = os.path.dirname(os.path.dirname(__file__))
    # 定义静态文件的路径
    static_dir = os.path.join(BASE_DIR, 'static')
    # 定义模板文件的路径
    templates_dir = os.path.join(BASE_DIR, 'templates')
    # 初始化app 和manage.py文件关联
    app = Flask(__name__,
                static_folder=static_dir,
                template_folder=templates_dir)
    # 注册蓝图
    app.register_blueprint(blueprint=user_blueprint, url_prefix='/user')
    # 配置mysql数据库
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:[email protected]:3306/Htai'
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

    # 设置session密钥
    app.config['SECRET_KEY'] = 'secret_key'
    # 设置连接的redis数据库 默认连接到本地6379
    app.config['SESSION_TYPE'] = 'redis'
    # 设置远程
    app.config['SESSION_REDIS'] = redis.Redis(host='127.0.0.1', port=6379)
    # 初始化db
    db.init_app(app=app)

    return app
4,登录验证的装饰器

from flask import url_for,redirect,session
from functools import wraps

def is_login(func):
    """
    定义登录注册验证的装饰器
    :return: check_login
    """
    @wraps(func)
    def check_login(*args,**kwargs):
        user_id = session.get('user_id')
        if user_id:
            return func(*args,**kwargs)
        else:
            return redirect(url_for('user.login'))
    return check_login
5,建立项目的模型

建立模型我们要对我们需求进行详细ORM(对象关系映射)的分析

student <————> grade 一对多

user <————> role 一对多

role <————> permission 多对多

from datetime import datetime
# 导入SQLAlchemy模块
from flask_sqlalchemy import SQLAlchemy
# 初始化db
db = SQLAlchemy()


class Grade(db.Model):
    """班级模型"""
    g_id = db.Column(db.Integer, autoincrement=True, primary_key=True)
    g_name = db.Column(db.String(20), unique=True)
    g_create_time = db.Column(db.DateTime, default=datetime.now)
    # 设置与班级 一对多的关联关系
    students = db.relationship('Student',backref= 'grade')
    # 自定义表名
    __tablename__ = 'grade'
    # 初始化字段 方便以后视图使用
    def __init__(self, name):
        self.g_name = name
    # 定义保存数据的方法 后面视图好使用
    def save(self):
        db.session.add(self)
        db.session.commit()


class Student(db.Model):
    """学生模型"""
    s_id = db.Column(db.Integer, autoincrement=True, primary_key=True)
    s_name = db.Column(db.String(16), unique=True)
    s_sex = db.Column(db.Integer)
    # 设置与班级 一对多的关联关系
    grade_id = db.Column(db.Integer, db.ForeignKey('grade.g_id'), nullable=True)

    __tablename__ = 'student'

    def __init__(self, s_name, s_sex,grade_id):
        self.s_name = s_name
        self.s_sex = s_sex
        self.grade_id =grade_id

    def save(self):
        db.session.add(self)
        db.session.commit()


class User(db.Model):
    """用户模型"""
    u_id = db.Column(db.Integer, autoincrement=True, primary_key=True)
    username = db.Column(db.String(16), unique=True)
    password = db.Column(db.String(250))
    u_create_time = db.Column(db.DateTime, default=datetime.now)
    # 用户和角色的一对多的关联关系
    role_id = db.Column(db.Integer, db.ForeignKey('role.r_id'))

    __tablename__ = 'user'

    def __init__(self,username,password):
        self.username = username
        self.password = password

    def save(self):
        db.session.add(self)
        db.session.commit()


# 角色和权限的(多对多的)关联表
# r_p为关联表的表名
r_p = db.Table('r_p',
               db.Column('role_id', db.Integer, db.ForeignKey('role.r_id'), primary_key=True),
               db.Column('permission_id', db.Integer, db.ForeignKey('permission.p_id'), primary_key=True))


class Role(db.Model):
    r_id = db.Column(db.Integer, autoincrement=True, primary_key=True)
    r_name = db.Column(db.String(10))
    # 用户和角色的一对多的关联关系
    users = db.relationship('User', backref='role')

    __tablename__ = 'role'

    def __init__(self,r_name):
        self.r_name = r_name

    def save(self):
        db.session.add(self)
        db.session.commit()


class Permission(db.Model):
    p_id = db.Column(db.Integer, autoincrement=True, primary_key=True)
    p_name = db.Column(db.String(16), unique=True)
    p_er = db.Column(db.String(16), unique=True)
    # 角色和权限的多对多的关系
    roles = db.relationship('Role', secondary=r_p, backref=db.backref('permission', lazy=True))

    __tablename__ = 'permission'

    def __init__(self,p_name,p_er):
        self.p_name = p_name
        self.p_er = p_er

    def save(self):
        db.session.add(self)
        db.session.commit()
6,在后台数据库中创建数据库为Htai的数据库
建库sql语句:
create database Htai default charset utf8;
7,开始写我们的视图中的代码
@user_blueprint.route('/create_db/')
def create_db():
    """
    创建数据
    """
    db.create_all()
    
    
@user_blueprint.route('/drop_db/')
def drop_db():
    """
    删除数据库
    """
    db.drop_all()
    return '删除成功'

执行这个地址就能把我们创建好的模型在数据库中创建好对应的表以供我们后续的功能的使用.

8,我们来实现第一个功能查看我们的首页
@user_blueprint.route('/home/', methods=['GET'])
@is_login
def home():
    """
    首页
    """
    if request.method == 'GET':
        return render_template('index.html')


@user_blueprint.route('/head/', methods=['GET'])
@is_login
def head():
    """
    页头
    """
    if request.method == 'GET':
        user = session.get('username')
        return render_template('head.html', user=user)


@user_blueprint.route('/left/', methods=['GET'])
def left():
    """左侧栏"""
    if request.method == 'GET':
        # 获取登录的用户信息
        user = session.get('username')
        # 获取用户的权限
        permissions = User.query.filter_by(username=user).first().role.permission
        return render_template('left.html', permissions=permissions)

这样我们就能看见我们初始项目的样子了.如下图


下面我们就一点一点的实现上面我们所说的功能,代码如下重要的内容我写好了注释

@user_blueprint.route('/register/', methods=['GET', 'POST'])
def register():
    """
    用户注册页面
    """
    if request.method == 'GET':
        return render_template('register.html')

    if request.method == 'POST':
        # 获取用户填写的信息
        username = request.form.get('username')
        pwd1 = request.form.get('pwd1')
        pwd2 = request.form.get('pwd2')

        # 定义个变量来控制过滤用户填写的信息
        flag = True
        # 判断用户是否信息都填写了.(all()函数可以判断用户填写的字段是否有空)
        if not all([username, pwd1, pwd2]):
            msg, flag = '* 请填写完整信息', False
        # 判断用户名是长度是否大于16
        if len(username) > 16:
            msg, flag = '* 用户名太长', False
        # 判断两次填写的密码是否一致
        if pwd1 != pwd2:
            msg, flag = '* 两次密码不一致', False
        # 如果上面的检查有任意一项没有通过就返回注册页面,并提示响应的信息
        if not flag:
            return render_template('register.html', msg=msg)
        # 核对输入的用户是否已经被注册了
        u = User.query.filter(User.username == username).first()
        # 判断用户名是否已经存在
        if u:
            msg = '用户名已经存在'
            return render_template('register.html', msg=msg)
        # 上面的验证全部通过后就开始创建新用户
        user = User(username=username, password=pwd1)
        # 保存注册的用户
        user.save()
        # 跳转到登录页面
        return redirect(url_for('user.login'))


@user_blueprint.route('/login/', methods=['GET', 'POST'])
def login():
    """
    登录
    """
    if request.method == 'GET':
        return render_template('login.html')

    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        # 判断用户名和密码是否填写
        if not all([username, password]):
            msg = '* 请填写好完整的信息'
            return render_template('login.html', msg=msg)
        # 核对用户名和密码是否一致
        user = User.query.filter_by(username=username, password=password).first()
        # 如果用户名和密码一致
        if user:
            # 向session中写入相应的数据
            session['user_id'] = user.u_id
            session['username'] = user.username
            return render_template('index.html')
        # 如果用户名和密码不一致返回登录页面,并给提示信息
        else:
            msg = '* 用户名或者密码不一致'
            return render_template('login.html', msg=msg)


@user_blueprint.route('/logout/', methods=['GET'])
def logout():
    """
    退出登录
    """
    if request.method == 'GET':
        # 清空session
        session.clear()
        # 跳转到登录页面
        return redirect(url_for('user.login'))


@user_blueprint.route('/grade/', methods=['GET', 'POST'])
@is_login
def grade_list():
    """
    显示班级列表
    """
    if request.method == 'GET':
        # 查询第几页的数据
        page = int(request.args.get('page',1))
        # 每页的条数是多少,默认为5条
        page_num = int(request.args.get('page_num',5))
        # 查询当前第几个的多少条数据
        paginate = Grade.query.order_by('g_id').paginate(page,page_num)
        # 获取某也的具体数据
        grades = paginate.items
        # 返回获取到的班级信息给前端页面
        return render_template('grade.html', grades=grades,paginate=paginate)


@user_blueprint.route('/addgrade/', methods=['GET', 'POST'])
@is_login
def add_grade():
    """添加班级"""
    if request.method == 'GET':
        return render_template('addgrade.html')

    if request.method == 'POST':
        g_name = request.form.get('g_name')
        g = Grade.query.filter(Grade.g_name == g_name).first()
        # 判断要添加的信息数据库中是否存在(因为班级名称不能重复)
        if g:
            msg = '*班级名称不能重复,请核对好在来添加'
            return render_template('addgrade.html', msg=msg)
        # 创建班级
        grade = Grade(g_name)
        # 保存班级信息
        grade.save()

        return redirect(url_for('user.grade_list'))


@user_blueprint.route('/edit_grade/', methods=['GET', 'POST'])
@is_login
def edit_grade():
    """编辑班级"""
    if request.method == 'GET':
        g_id = request.args.get('g_id')
        g_name = Grade.query.filter(Grade.g_id == g_id).first().g_name
        return render_template('addgrade.html', g_name=g_name, g_id=g_id)

    if request.method == 'POST':
        # 获取需要修改的班级id
        g_id = request.form.get('g_id')
        g_name = request.form.get('g_name')
        # 通过获取到的班级id
        grade = Grade.query.filter(Grade.g_id == g_id).first()
        # 重新给班级赋值
        grade.g_name = g_name
        grade.save()

        return redirect(url_for('user.grade_list'))


@user_blueprint.route('/grade_student/', methods=['GET'])
@is_login
def grade_students_list():
    """班级中学习的信息列表"""
    if request.method == 'GET':
        g_id = request.args.get('g_id')
        stus = Student.query.filter(Student.grade_id == g_id).all()
        return render_template('student.html', stus=stus)


@user_blueprint.route('/student/', methods=['GET', 'POST'])
@is_login
def student_list():
    """学生信息列表"""
    if request.method == 'GET':
        page = int(request.args.get('page',1))
        page_num = int(request.args.get('page_num',5))
        paginate = Student.query.order_by('s_id').paginate(page,page_num)
        stus = paginate.items
        return render_template('student.html', stus=stus,paginate=paginate)


@user_blueprint.route('/addstu/', methods=['GET', 'POST'])
@is_login
def add_stu():
    """添加学生"""
    if request.method == 'GET':
        grades = Grade.query.all()
        return render_template('addstu.html', grades=grades)

    if request.method == 'POST':
        s_name = request.form.get('s_name')
        s_sex = request.form.get('s_sex')
        grade_id = request.form.get('g_name')

        stu = Student.query.filter(Student.s_name == s_name).first()
        if stu:
            msg = '* 学习姓名不能重复'
            grades = Grade.query.all()
            return render_template('addstu.html', grades=grades, msg=msg)
        stu = Student(s_name=s_name, s_sex=s_sex, grade_id=grade_id)
        stu.save()

        return redirect(url_for('user.student_list'))


@user_blueprint.route('/roles/', methods=['GET', 'POST'])
@is_login
def roles_list():
    """角色信息列表"""
    if request.method == 'GET':
        roles = Role.query.all()
        return render_template('roles.html', roles=roles)


@user_blueprint.route('/addroles/', methods=['GET', 'POST'])
@is_login
def add_roles():
    """添加角色"""
    if request.method == 'GET':
        return render_template('addroles.html')
    if request.method == 'POST':

        r_name = request.form.get('r_name')
        role = Role(r_name=r_name)
        role.save()

        return redirect(url_for('user.roles_list'))


@user_blueprint.route('/userperlist/', methods=['GET', 'POST'])
@is_login
def user_per_list():
    """用户权限列表"""
    if request.method == 'GET':
        r_id = request.args.get('r_id')
        pers = Role.query.filter(Role.r_id == r_id).first().permission
        return render_template('user_per_list.html', pers=pers)

    if request.method == 'POST':
        r_id = request.args.get('r_id')
        p_id = request.form.get('p_id')
        # 获取到角色对象
        role = Role.query.get(r_id)
        # 获取到权限对象
        per = Permission.query.get(p_id)
        # 解除角色和权限的对应关系
        per.roles.remove(role)
        # 保存解除的关联的信息
        db.session.commit()
        pers = Role.query.filter(Role.r_id == r_id).first().permission
        # 返回到用户权限列表
        return render_template('user_per_list.html', pers=pers, r_id=r_id)


@user_blueprint.route('/adduserper/', methods=['GET', 'POST'])
@is_login
def add_user_per():
    """添加用户权限"""
    if request.method == 'GET':
        permissions = Permission.query.all()
        r_id = request.args.get('r_id')
        return render_template('add_user_per.html', permissions=permissions, r_id=r_id)

    if request.method == 'POST':
        r_id = request.form.get('r_id')
        p_id = request.form.get('p_id')
        # 获取角色对象
        role = Role.query.get(r_id)
        # 获取权限对象
        per = Permission.query.get(p_id)
        # 添加对应的角色和权限的对应关系
        per.roles.append(role)
        # 添加
        db.session.add(per)
        # 保存信息
        db.session.commit()

        return redirect(url_for('user.roles_list'))


@user_blueprint.route('/subuserper/', methods=['GET', 'POST'])
@is_login
def sub_user_per():
    """减少用户权限"""
    if request.method == 'GET':
        r_id = request.args.get('r_id')
        pers = Role.query.filter(Role.r_id == r_id).first().permission
        return render_template('user_per_list.html', pers=pers, r_id=r_id)

    if request.method == 'POST':
        r_id = request.args.get('r_id')
        p_id = request.form.get('p_id')
        role = Role.query.get(r_id)
        per = Permission.query.get(p_id)

        # 解除角色和权限的对应关系
        per.roles.remove(role)
        db.session.commit()

        pers = Role.query.filter(Role.r_id == r_id).first().permission
        return render_template('user_per_list.html', pers=pers, r_id=r_id)


@user_blueprint.route('/permissions/', methods=['GET', 'POST'])
@is_login
def permission_list():
    """权限列表"""
    if request.method == 'GET':
        permissions = Permission.query.all()
        return render_template('permissions.html', permissions=permissions)


@user_blueprint.route('/addpermission/', methods=['GET', 'POST'])
@is_login
def add_permission():
    """添加权限"""
    if request.method == 'GET':
        pers = Permission.query.all()
        return render_template('addpermission.html', pers=pers)

    if request.method == 'POST':
        p_name = request.form.get('p_name')
        p_er = request.form.get('p_er')

        p_name_test_repeat = Permission.query.filter(Permission.p_name == p_name).first()
        if p_name_test_repeat:
            msg = '*权限名称重复'
            return render_template('addpermission.html', msg=msg)

        p_er_test_repeat = Permission.query.filter(Permission.p_er == p_er).first()

        if p_er_test_repeat:
            msg1 = '*权限简写名重复'
            return render_template('addpermission.html', msg1=msg1)

        permission = Permission(p_name=p_name, p_er=p_er)
        permission.save()

        return redirect(url_for('user.permission_list'))


@user_blueprint.route('/eidtorpermission/', methods=['GET', 'POST'])
@is_login
def eidtor_permission():
    """编辑权限"""
    if request.method == 'GET':
        p_id = request.args.get('p_id')
        pers = Permission.query.filter(Permission.p_id == p_id).first()
        return render_template('addpermission.html', pers=pers, p_id=p_id)
    if request.method == 'POST':
        p_id = request.form.get('p_id')
        p_name = request.form.get('p_name')
        p_er = request.form.get('p_er')

        p_name_test_repeat = Permission.query.filter(Permission.p_name == p_name).first()
        if p_name_test_repeat:
            msg = '*权限名称重复'
            pers = Permission.query.all()
            return render_template('addpermission.html', msg=msg, pers=pers)

        p_er_test_repeat = Permission.query.filter(Permission.p_er == p_er).first()

        if p_er_test_repeat:
            msg1 = '*权限简写名重复'
            pers = Permission.query.all()
            return render_template('addpermission.html', msg1=msg1, pers=pers)

        per = Permission.query.filter(Permission.p_id == p_id).first()
        per.p_name = p_name
        per.p_er = p_er
        db.session.commit()

        return redirect(url_for('user.permission_list'))


@user_blueprint.route('/userlist/', methods=['GET', 'POST'])
@is_login
def user_list():
    """用户信息列表"""
    if request.method == 'GET':
        page = int(request.args.get('page',1))
        page_num = int(request.args.get('page_num',5))
        paginate = User.query.order_by('u_id').paginate(page,page_num)
        users = paginate.items
        return render_template('users.html', users=users,paginate=paginate)


@user_blueprint.route('/adduser/', methods=['GET', 'POST'])
@is_login
def add_user():
    """添加用户信息"""
    if request.method == 'GET':
        return render_template('adduser.html')

    if request.method == 'POST':
        username = request.form.get('username')
        password1 = request.form.get('password1')
        password2 = request.form.get('password2')

        flag = True
        if not all([username, password1, password2]):
            msg, flag = '请填写完整信息', False
        if len(username) > 16:
            msg, flag = '用户名太长', False
        if password1 != password2:
            msg, flag = '两次密码不一致', False
        if not flag:
            return render_template('adduser.html', msg=msg)
        user = User(username=username, password=password1)
        user.save()
        return redirect(url_for('user.user_list'))


@user_blueprint.route('/assignrole/', methods=['GET', 'POST'])
@is_login
def assign_user_role():
    """分配用户权限"""
    if request.method == 'GET':
        u_id = request.args.get('u_id')
        roles = Role.query.all()
        return render_template('assign_user_role.html', roles=roles, u_id=u_id)
    if request.method == 'POST':
        r_id = request.form.get('r_id')
        u_id = request.form.get('u_id')
        user = User.query.filter_by(u_id=u_id).first()
        user.role_id = r_id
        db.session.commit()

        return redirect(url_for('user.user_list'))


@user_blueprint.route('/changepwd/', methods=['GET', 'POST'])
@is_login
def change_password():
    """修改用户密码"""
    if request.method == 'GET':
        username = session.get('username')
        user = User.query.filter_by(username=username).first()
        return render_template('changepwd.html', user=user)

    if request.method == 'POST':
        username = session.get('username')
        pwd1 = request.form.get('pwd1')
        pwd2 = request.form.get('pwd2')
        pwd3 = request.form.get('pwd3')

        pwd = User.query.filter(User.password == pwd1, User.username == username).first()
        if not pwd:
            msg = '请输入正确的旧密码'
            username = session.get('username')
            user = User.query.filter_by(username=username).first()
            return render_template('changepwd.html', msg=msg, user=user)
        else:
            if not all([pwd2, pwd3]):
                msg = '密码不能为空'
                username = session.get('username')
                user = User.query.filter_by(username=username).first()
                return render_template('changepwd.html', msg=msg, user=user)
            if pwd2 != pwd3:
                msg = '两次密码不一致,请重新输入'
                username = session.get('username')
                user = User.query.filter_by(username=username).first()
                return render_template('changepwd.html', msg=msg, user=user)
            pwd.password = pwd2
            db.session.commit()
            return redirect(url_for('user.change_pass_sucess'))


@user_blueprint.route('/changepwdsu/', methods=['GET'])
@is_login
def change_pass_sucess():
    """修改密码成功后"""
    if request.method == 'GET':
        return render_template('changepwdsu.html')

到这里我们的项目的功能就完全实现了.

比较重要的地方有分页效果. 在我们数据量大了如何去处理分页数据

后端代码
@user_blueprint.route('/grade/', methods=['GET', 'POST'])
@is_login
def grade_list():
    """
    显示班级列表
    """
    if request.method == 'GET':
        # 查询第几页的数据
        page = int(request.args.get('page',1))
        # 每页的条数是多少,默认为5条
        page_num = int(request.args.get('page_num',5))
        # 查询当前第几个的多少条数据
        paginate = Grade.query.order_by('g_id').paginate(page,page_num)
        # 获取某也的具体数据
        grades = paginate.items
        # 返回获取到的班级信息给前端页面
        return render_template('grade.html', grades=grades,paginate=paginate)
前端代码
<div id="MainForm">
    <div class="form_boxA">
        <h2>班级信息列表</h2>
        <table cellpadding="0" cellspacing="0">
            <tr>
                <th>序号</th>
                <th>班级名称</th>
                <th>创建时间</th>
                <th>操作</th>
            </tr>
            {% for grade in grades %}
            <tr>
                <td>{{grade.g_id }}</td>
                <td>{{grade.g_name }}</td>
                <td>{{grade.g_create_time}}</td>
                <td>
                    <a href="/user/edit_grade/?g_id={{grade.g_id }}">编辑</a> |
                    <a href="#">删除</a> |
                    <a href="/user/grade_student/?g_id={{grade.g_id}}">查看学生</a>
                </td>
            </tr>
            {% endfor %}
        </table>
        <p class="msg">共找到{{paginate.total}}条匹配记录</p>
    </div>


<ul id="PageNum">

        <li><a href="/user/grade/?page=1">首页</a></li>
        {% if paginate.has_prev %}
            <li><a href="/user/grade/?page={{ paginate.prev_num }}">上一页</a></li>
        {% endif %}

        {% for p  in paginate.iter_pages() %}
            <li>
                {% if p %}
                    {% if p != paginate.page %}
                    <a href="/user/grade/?page={{ p }}">{{ p }}</a>
                    {% else %}
                    <span> {{ p }} </span>
                    {% endif %}
                {% else %}
                    <span>...</span>
                {% endif %}
            </li>
        {% endfor  %}

        {% if paginate.has_next %}
            <li><a href="/user/grade/?page={{ paginate.next_num }}">下一页</a></li>
        {% endif %}
            <li><a href="/user/grade/?page={{ paginate.pages }}">尾页</a></li>
        <span>| 共{{paginate.pages}}页 | 当前第{{paginate.page}}页</span>
    </ul>

项目所有的页面有:


需要练习的我都把所有的代码放git上面了.可以去下载哦!!希望对大家学习有帮助.

下载地址:
https://github.com/Leezhonglin/learingnote/tree/master/flask/flask项目

猜你喜欢

转载自blog.csdn.net/qq_33196814/article/details/80866094