管理信息系统第二学期课程设计

Posted betty18

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了管理信息系统第二学期课程设计相关的知识,希望对你有一定的参考价值。

----------系统概要-------------
1. 基于python3版本,flask框架开发的新闻平台,采用前后端不分离的方式
2. 具有基本登陆,注册
3. 用户可以进行新闻的发布修改
4. 用户可以修改个人信息
5. 在新闻详细页具体关注新闻,关注作者,发表评论,回复评论等功能
6. 后台管理,管理员可以对新闻进行审核,并新增新闻分类

---------网站结构设计-------------
1.新闻主页,可以查看新闻列表,最热新闻,查看不同分类的新闻,通过ajax进行局部刷新,往下滑自动加载下一页
2.用户登陆,注册
3.新闻详细页,有评论点赞,作者信息
4.用户个人中心,修改个人信息,发布信息,查看关注作者
5.后台管理,新闻全部信息,审核新闻,增加分类

------------模块详细设计-----------

登陆注册模块

登陆
@user_blueprint.route(/login, methods=[POST])
def login():
    # 接收数据
    dict1 = request.form
    mobile = dict1.get(mobile)
    pwd = dict1.get(pwd)

    # 验证有效性
    if not all([mobile, pwd]):
        return jsonify(result=1)

    # 查询判断、响应
    user = UserInfo.query.filter_by(mobile=mobile).first()
    # 判断mobile是否正确
    if user:
        # 进行密码对比,flask内部提供了密码加密、对比的函数
        if user.check_pwd(pwd):
            # 将当前时段的登录数量+1
            login_time_count()
            # 状态保持
            session[user_id] = user.id
            # 返回成功的结果
            return jsonify(result=4, avatar=user.avatar_url, nick_name=user.nick_name)
        else:
            # 密码错误
            return jsonify(result=3)
    else:
        # 如果查询不到数据返回None,表示mobile错误
        return jsonify(result=2)

注册模块
ef register():
    # 接收数据
    dict1 = request.form
    mobile = dict1.get(mobile)
    yzm_image = dict1.get(yzm_image)
    yzm_sms = dict1.get(yzm_sms)
    pwd = dict1.get(pwd)

    # 验证数据的有效性
    # 保证所有的数据都被填写,列表中只要有一个值为False,则结果为False
    if not all([mobile, yzm_image, yzm_sms, pwd]):
        return jsonify(result=1)
    # 对比图片验证码
    if yzm_image != session[image_yzm]:
        return jsonify(result=2)
    # 对比短信验证码
    if int(yzm_sms) != session[sms_yzm]:
        return jsonify(result=3)
    # 判断密码的长度
    import re
    if not re.match(r[a-zA-Z0-9_]{6,20}, pwd):
        return jsonify(result=4)
    # 验证mobile是否存在
    mobile_count = UserInfo.query.filter_by(mobile=mobile).count()
    if mobile_count > 0:
        return jsonify(result=5)

    # 创建对象
    user = UserInfo()
    user.nick_name = mobile
    user.mobile = mobile
    user.password = pwd
    # user.avatar = ‘cat.jpg‘
    # 提交到数据库
    try:
        db.session.add(user)
        db.session.commit()
    except:
        current_app.logger_xjzx.error(用户注册访问数据库失败)
        return jsonify(result=7)

    # 返回响应
    return jsonify(result=6)

访问其他视图时,验证是否登陆(装饰器)

def login_required(view_fun):
    @functools.wraps(view_fun)  # 保持view_fun的函数名称不变,不会被fun2这个名称代替
    def fun2(*args, **kwargs):
        # 判断用户是否登录
        if user_id not in session:
            return redirect(/)
        # 视图执行完,会返回response对象,此处需要将response对象继续return,最终交给浏览器
        return view_fun(*args, **kwargs)

    return fun2

管理员模块

管理员登陆
@admin_blueprint.route(/login, methods=[GET, POST])
def login():
    if request.method == GET:
        return render_template(admin/login.html)
    elif request.method == POST:
        # 接收
        dict1 = request.form
        mobile = dict1.get(username)
        pwd = dict1.get(password)
        # 验证
        if not all([mobile, pwd]):
            return render_template(
                admin/login.html,
                msg=请填写用户名、密码
            )
        # 处理
        user = UserInfo.query.filter_by(isAdmin=True, mobile=mobile).first()
        if user is None:
            return render_template(
                admin/login.html,
                mobile=mobile,
                pwd=pwd,
                msg=用户名错误
            )
        if not user.check_pwd(pwd):
            return render_template(
                admin/login.html,
                mobile=mobile,
                pwd=pwd,
                msg=密码错误
            )
        # 登录成功后,进行状态保持
        session[admin_user_id] = user.id
        # 响应
        return redirect(/admin/)
访问其他视图,验证是否登陆状态(请求勾子)
@admin_blueprint.before_request
def login_validate():
    # 对于不执行这段代码的视图,可以进行排除
    except_path_list = [/admin/login]
    if request.path not in except_path_list:
        if admin_user_id not in session:
            return redirect(/admin/login)
        g.user = UserInfo.query.get(session[admin_user_id])

新闻模块

展示新闻列表
@news_blueprint.route(/newslist)
def newslist():
    # 查询新闻数据==>[news,news,...]==>json
    # 接收请求的页码值
    page = int(request.args.get(page, 1))
    # 查询新闻信息
    pagination = NewsInfo.query.filter_by(status=2)
    # 接收分类的编号
    category_id = int(request.args.get(category_id, 0))
    if category_id:
        pagination = pagination.filter_by(category_id=category_id)
    # 排序,分页
    pagination = pagination.         order_by(NewsInfo.update_time.desc()).         paginate(page, 4, False)
    # 获取当前页的数据
    news_list = pagination.items
    # pagination.pages
    # 将python语言中的类型转换为json
    news_list2 = []
    for news in news_list:
        # print(news.pic_url)
        news_dict = {
            id: news.id,
            pic: news.pic_url,
            title: news.title,
            summary: news.summary,
            user_avatar: news.user.avatar_url,
            user_nick_name: news.user.nick_name,
            update_time: news.update_time.strftime(%Y-%m-%d),
            user_id: news.user.id,
            category_id: news.category_id
        }
        news_list2.append(news_dict)

    return jsonify(news_list=news_list2)


新闻首页
@news_blueprint.route(/)
def index():
    # 查询分类,用于显示
    category_list = NewsCategory.query.all()

    # 判断用户是否登录
    if user_id in session:
        user = UserInfo.query.get(session[user_id])
    else:
        user = None

    # 获取分类排行前6条数据select * from ... where ... order ... limit 6
    count_list = NewsInfo.query.                      filter_by(status=2).                      order_by(NewsInfo.click_count.desc())[0:6]

    return render_template(
        news/index.html,
        category_list=category_list,
        user=user,
        count_list=count_list
    )

 


1. 用户views_user.py模块
注册
本质:向用户表中加入数据
展示页面
views_news.py
index.html
图片验证码
使用python的绘图工具PIL进行绘制,返回给浏览器
pip install pillow
拷贝captcha到utils包
在views_user.py定义视图
在index.html中调用
看不清换一张
短信验证码
调用第三方的接口进行短信处理
拷贝sdk
定义调用代码ytx_send.py
在views_user.py中定义视图
在js中调用
注册处理views_user.py
使用post方式请求
CSRF保护
在app对象上进行保护
csrf_token()
接收数据
验证数据的有效性
创建user对象并赋值
提交到数据库
响应
调用
登录
本质:根据用户名密码查询数据
视图处理
获取数据
有效性判断
处理:查询
判断响应:用户名、密码
登录成功后状态保持
调用
退出
右上角信息显示
登录视图中返回用户信息
登录处理中显示信息
视图:删除cookie值
调用
用户中心
视图index
模板user.html
展示昵称、头像
完善链接
user.html
定义相关视图
user.html代码重用
定义base.html,封装头、尾
在user.html中继承
登录验证
在访问用户中心的相关视图时,必须登录,否则转到首页
定义装饰器
添加到视图函数上
在用户中心退出时转到首页
基本资料
显示原有数据
视图:查询
模板:展示
提交处理
使用ajax+post
视图:接收数据并修改对象
调用:提交,成功后修改页面
头像设置
展示
视图:查询
模板:展示
如何在flask中进行图片上传
将文件上传到服务器,保存在磁盘上,然后将文件名保存在表的字段上
HTML要求
form表单的method="post"
表单的 enctype="multipart/form-data"
flask处理
接收文件request.files.get(‘与input的name一致‘)
保存:文件对象.save(路径)
将文件名赋给对象的属性:文件对象.name
将文件上传到七牛云
如何使用ajax方式进行文件上传:jquery.form.min.js
提交
视图处理
调用及成功后显示
访问腾讯云的图片
我的关注
查询数据并展示
视图中查询
模板中展示
添加示例数据:
user_info,tb_user_follow
分页
查询语句中有方法paginate(页码,页大小,False)
在视图中分页查询
在模板中调用jquery.pagination.min.js
我的收藏
视图:查询并分页
模板:展示,页码控制
新闻列表
视图:查询并分页
模板:展示,页码控制
密码修改
展示
定义视图
模板显示
处理
post
问题分析
视图处理
响应
新闻发布
展示
定义视图:查询新闻分类
模板显示
处理
视图接收添加
页面news_list.html
main.js
新闻修改
展示
视图:查询数据
模板:展示
处理
视图:接收并保存
转到列表页


2. 新闻views_news.py模块

功能分析
首页
新闻列表
分页(向下滑动,到底部时加载)
显示分类
指定分类的列表+分页
登录状态
点击量排行列表
模板继承
详情页
模板继承
根据新闻编号查询新闻并展示
收藏与取消收藏
评论
评论列表
回复评论
点赞评论
作者信息
关注与取消关注
点击排行(重用:宏)
首页
定义视图,显示页面
模板继承
继承自base.html
index.html
所有分类
视图
模板
登录状态
视图
模板base.html
main.js
views_user中的login视图
新闻列表
使用ajax方式查询数据
使用vue渲染页面
视图news_list:查询
复制vue.js到项目中
显示:index.html
index.js
函数updateNewsData
分页
当进行$.get()请求后,数据不会立即返回,但是<100的判断还在执行,这样会发起多次请求,解决:增加一个请求标志
视图
index.js
分类数据查询
视图
如果请求是第一页,则直接为vue赋值
如果请求非第一页,则为vue的数组进行拼接
index.js中请求调用
分页的完善:index.js
updateNewsData
点击排行
在index.html中显示
详情页
定义视图,展示页面
app.py中处理404
视图函数detail
模板继承
登录状态
显示新闻信息{{news.***}}
点击排行:重用(宏)
macro.html
index.html使用
detail.html使用
视图中查询点击排行数据
收藏
如果当前新闻的作者与当前登录的用户是同一个账户,则不显示收藏的按钮
定义视图:数据添加
在detail.html中加入新闻编号、口令
使用ajax请求视图
取消收藏-视图
取消收藏-调用
添加评论
定义视图,添加数据
js调用
界面提示
评论列表
ajax+vue
定义视图,查询数据,返回json
js调用:$.get()
vue模板定义
在js中创建vue对象并调用
点赞
post,局部刷新
定义视图,处理数据,user_id-comment_id,存储在redis中
js调用
界面样式切换
commentlist视图
app.py
detail.html中的vue模板
取消点赞
视图中处理
js中调用
回复
定义视图,添加数据
js调用$.post
展示

关注
定义视图,处理数据
默认展示效果
$.post()调用

3. 后台views_admin.py 模块


后台views_admin.py
功能分析
登录
登出
后台管理页面
访问验证
用户统计
用户列表
新闻审核列表
新闻审核
新闻版式编辑列表
新闻版式编辑
新闻分类管理(局部刷新)
创建管理员
方案一:直接在数据库中执行insert语句
方案二:直接在前台注册,在表中修改isAdmin属性
解决:扩展终端命令,进行添加管理员
创建命令类super_command.py
添加扩展命令xjzx.py
登录
定义视图,展示页面
模板login.html
接收post请求,查询数据,状态保持
后台主页
定义视图
修改模板:维护链接
用户信息
菜单的修改
退出
定义视图
登录验证
判断是否登录,如果未登录则转到登录页面
大部分视图都要进行这个验证,除了/admin/login
方案一:装饰器(已经在用户中心中使用过)
方案二:请求勾子before_request
用户统计
定义视图
展示页面
需要展示的数据
用户总数
用户月新增数
用户日新增数
用户登录活跃数
注册登录
登录分时统计
登录成功时写数据(views_user.py==>login)
在用户统计时读数据
用户列表
定义视图:展示页面
展示模板vue
定义视图:返回json数据
新闻审核列表
展示视图
展示模板
列表视图
新闻版式编辑列表
展示视图
展示模板
列表视图
新闻审核列表-搜索
视图
html
js调用
新闻版式编辑列表-搜索
视图
html
js调用
新闻审核
get请求视图,展示页面
模板
post请求视图,修改新闻状态
新闻版式编辑
get视图
模板
post视图
新闻分类管理
无刷新
页面视图
模板vue
json视图
js调用news_type.js
添加
视图
js
修改
视图
js

-----------数据结构和算法-------------
1. 将常用的数据存入redis数据库提升数据查询效率
。。。。。。。


-----------数据库设计--------------

ORM(数据库设计)

import pymysql
from flask import current_app
from werkzeug.security import generate_password_hash, check_password_hash

pymysql.install_as_MySQLdb()

from flask_sqlalchemy import SQLAlchemy

db=SQLAlchemy()

from datetime import datetime
class BaseModel(object):
    create_time=db.Column(db.DateTime,default=datetime.now)
    update_time=db.Column(db.DateTime,default=datetime.now)
    isDelete=db.Column(db.Boolean,default=False)

tb_news_collect = db.Table(
    tb_news_collect,
    db.Column(user_id, db.Integer, db.ForeignKey(user_info.id), primary_key=True),
    db.Column(news_id, db.Integer, db.ForeignKey(news_info.id), primary_key=True)
)
tb_user_follow = db.Table(
    tb_user_follow,
    db.Column(origin_user_id, db.Integer, db.ForeignKey(user_info.id), primary_key=True),
    db.Column(follow_user_id, db.Integer, db.ForeignKey(user_info.id), primary_key=True)
)


class NewsCategory(db.Model, BaseModel):
    __tablename__ = news_category
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(10))
    #关系属性:不会在表中生成字段
    #lazy=dynamic惰性加载category.news
    #category=NewsCategory.query.get(1)
    #当使用lazy=dynamic时不会查询分类的新闻信息
    #这样设置的好处:可能本次只是使用分类对象,不想使用新闻对象,则可以减少数据库的查询量
    news = db.relationship(NewsInfo, backref=category, lazy=dynamic)


class NewsInfo(db.Model, BaseModel):
    __tablename__ = news_info
    id = db.Column(db.Integer, primary_key=True)
    category_id = db.Column(db.Integer, db.ForeignKey(news_category.id))
    pic = db.Column(db.String(50))
    title = db.Column(db.String(30))
    summary = db.Column(db.String(200))
    content = db.Column(db.Text)
    user_id = db.Column(db.Integer, db.ForeignKey(user_info.id))
    click_count = db.Column(db.Integer, default=0)
    comment_count = db.Column(db.Integer, default=0)
    #1--待审核,2--通过,3--拒绝
    status = db.Column(db.SmallInteger, default=1)
    reason=db.Column(db.String(100),default=‘‘)
    comments = db.relationship(NewsComment, backref=news, lazy=dynamic, order_by=NewsComment.id.desc())

    @property
    def pic_url(self):
        from config import Config
        return Config.tengxun_URL + self.pic

    # def to_index_dict(self):
    #     return {
    #         id: self.id,
    #         pic_url: self.pic_url,
    #         title: self.title,
    #         summary: self.summary,
    #         author: self.user.nick_name,
    #         author_avatar: self.user.avatar_url,
    #         author_id: self.user_id,
    #         udpate_time: self.update_time.strftime(%Y-%m-%d)
    #     }


class UserInfo(db.Model,BaseModel):
    __tablename__ = user_info
    id = db.Column(db.Integer, primary_key=True)
    avatar = db.Column(db.String(50), default=user_pic.png)
    nick_name = db.Column(db.String(20))
    signature = db.Column(db.String(200),default=这货很懒,什么也没写)
    public_count = db.Column(db.Integer, default=0)
    follow_count = db.Column(db.Integer, default=0)
    mobile = db.Column(db.String(11))
    password_hash = db.Column(db.String(200))
    gender = db.Column(db.Boolean, default=False)
    isAdmin = db.Column(db.Boolean, default=False)
    #用户发布新闻为1:多,所以将新闻关联属性定义在User类中
    news = db.relationship(NewsInfo, backref=user, lazy=dynamic)
    #用户对评论为1:多,所以将评论关联属性定义在User类中
    comments = db.relationship(NewsComment, backref=user, lazy=dynamic)
    #用户对收藏新闻为多:多,此时关系属性可以定义在任意类中,当前写在了User类中
    news_collect = db.relationship(
        NewsInfo,
        #多对多时,指定关系表,因为外键存储在这个关系表中
        secondary=tb_news_collect,
        lazy=dynamic
        #此处没有定义backref,作用是根据新闻找用户,因为不需要使用这个功能,所以可以不定义
    )
    #用户关注用户为自关联多对多,关系属性只能定义在User类中
    #使用user.follow_user可以获得当前user用户关注的用户列表
    #select * from users inner join tb_user_follow on user.id=origin_user_id
    follow_user = db.relationship(
        UserInfo,
        #多对多,所以指定关系表
        secondary=tb_user_follow,
        lazy=dynamic,
        #user.follow_by_user可以获得当前user用户的粉丝用户列表
        backref=db.backref(follow_by_user, lazy=dynamic),
        #在使用user.follow_user时,user.id与关系表中哪个字段判等
        primaryjoin=id == tb_user_follow.c.origin_user_id,
        #在使用user.follow_by_user时,user.id与关系表中的哪个字段判等
        secondaryjoin=id == tb_user_follow.c.follow_user_id
    )

    @property
    def password(self):
        pass

    @password.setter
    def password(self, pwd):
        self.password_hash = generate_password_hash(pwd)

    def check_pwd(self, pwd):
        return check_password_hash(self.password_hash, pwd)

    @property#user.avatar_url()==>user.avatar_url
    def avatar_url(self):
        from config import Config
        # print(Config.tengxun_URL)
        return Config.tengxun_URL+self.avatar

class NewsComment(db.Model, BaseModel):
    __tablename__ = news_comment
    id = db.Column(db.Integer, primary_key=True)
    news_id = db.Column(db.Integer, db.ForeignKey(news_info.id))
    user_id = db.Column(db.Integer, db.ForeignKey(user_info.id))
    like_count = db.Column(db.Integer, default=0)
    comment_id = db.Column(db.Integer, db.ForeignKey(news_comment.id))
    msg = db.Column(db.String(200))
    #关联属性,用于获取当前评论的回复数据
    comments = db.relationship(NewsComment, lazy=dynamic)

 

1. 新闻分类(category)
id, name, is_delete
2.新闻(news_info)
id, title, category_id(category外键) ,pic ,summary ,context ,user_id(user外键) ,source ,click_count ,comment_count ,status ,reason

3.用户关注用户关系
用户关注用户,自关联多对多

4. 用户收藏新闻关系表
用户与新闻一对多

5, 用户

6. 评论

技术分享图片技术分享图片技术分享图片技术分享图片技术分享图片技术分享图片
























































































































































































































































































































































以上是关于管理信息系统第二学期课程设计的主要内容,如果未能解决你的问题,请参考以下文章

[WUT]武理四年课程实验导航

学生信息管理系统C语言编程

管理信息系统 课程设计——201502010152陈斯璐

c语言学生成绩管理系统设计

武理四年课程实验导航

20155234 2017-2018-1《信息安全系统设计基础》课程总结