系统概要说明
现在,随着物联网以及网络技术的飞速发展,互联网已经成为了人们发布与获取信息的重要途径之一,所以通过老师要求,我们设计了一个普通的公司管理信息系统网站。这网站的具有的功能有注册,登录,注销,发布,列表展示,详情页,评论(列表显示),个人中心,搜索,条件组合搜索,文章分类,显示,点赞,收藏,修改密码,上传头像,我的发布(点赞),高级搜索等一系列功能。
一.网站结构设计
二.模块详细设计
2.1基本功能
{% block title %}{% endblock %}首页 {% block head %}{% endblock %} {% block main %}{% for foo in fenlei %}
- { {foo.name}}
{% endfor %}
- {% for foo in questions %}
- { { foo.title }}{#链接到相关详情页#} { { foo.create_time }}
{
{ foo.detail }} { { foo.author.username }}评论:({ { foo.comments|length }}) {% endfor %}
首页基本页面显示功能,其中包含提问,搜索,注销,登录,注册等显示
2.2问答详情功能
{% extends'base.html' %} {% block title %}问答详情{% endblock %} {% block head %} {% endblock %} {% block main %}{#发布评论#} {# 评论列表#}题目:{ { questions.title }} 作者:{ { questions.author.username }} 发布时间:{ { questions.create_time }}
详情:{
{ questions.detail }}
评论({ { questions.comments|length }})
- {% for foo in questions.comments %}
- { { foo.author.username }} { { foo.create_time }}
{
{ foo.detail }} {% endfor %}
问答详情功能里面包含点赞功能,收藏,评论功能。
2.3注册功能
{% extends'base.html' %}
{% block title %}注册{% endblock %} {% block head %} <link rel="stylesheet" type="text/css" href="{ { url_for('static',filename='css/enroll.css') }}"> <script src="{ { url_for('static',filename='js/enroll.js') }}"></script> {% endblock %} {% block main %} <div class="box"> <h2>注册</h2> <form action="{ { url_for('enroll') }}" method="post"> <div class="input_box"> username:<input id="zname" type="text"placeholder="设置您的用户名" name="username"><br> <!--yourname:<input id="znickname" type="text"placeholder="设置您的昵称" name="nickname">--> </div> <div class="input_box"> password:<input id="zpass1" type="password"placeholder="设置您的密码" name="password"><br> <!--</div>--> <!--<div class="input-box">--> twowrite:<input id="zpass2" type="password" placeholder="重新输入一样的密码"> </div> <div class="input_box"> <a href="{ { url_for('login') }}" style="margin: 10px">已有账号,登录</a> </div> <div id="error_box"><br></div> <div class="input_box"> <button class="button" οnclick="fnEnroll()">立即注册</button> </div> </form> </div> {% endblock %}
2.4登录功能
{% extends'base.html' %}
{% block title %}登录{% endblock %} {% block head %} <link rel="stylesheet" type="text/css" href="{ { url_for('static',filename='css/login.css') }}"> <script src="{ { url_for('static',filename='/js/login.js')}}"></script> {% endblock %} {% block main %} <div class="box"> <h2>登录</h2> <form action="{ { url_for('login') }}" method="post"> <div class="input_box"> username:<input id="uname" type="text"placeholder="请输入用户名" name="username"> </div> <div class="input_box"> yourname<input id="unickname" type="text"placeholder="请输入昵称" name="nickname"> </div> <div class="input_box"> password:<input id="upass" type="password"placeholder="请输入密码" name="password"> </div> <div class="input_box"> <a href="{ { url_for('enroll') }}">没有账号?立即注册</a> </div> <div id="error_box"><br></div> <div class="input_box"> <button class="button" οnclick="fnLogin()">登录</button> </div> </form> </div> {% endblock %}2.5 发布问答功能
{% extends'base.html' %}
{% block title %}发布问答{% endblock %} {% block head %} <link rel="stylesheet" href="{ { url_for('static',filename='css/questions.css') }}" type="text/css"> {% endblock %} {% block main %} <div class="box"> <h2>发布问答</h2> <form action="{ { url_for('questions') }}" method="post"> <div class="input-box"> <lable for="title">标题</lable> <textarea class="form-control" id="title" rows="1" cols="50" name="title"></textarea> </div> <div class="input-box"> <select name="fenlei_id" id=""> {% for foo in fenlei %} <option value="{ {foo.id}}">{ {foo.name}}</option> {% endfor %} </select> </div> <div class="input-box"> <lable for="detail">详情</lable> <textarea class="form-control" id="detail" rows="5" cols="50" name="detail"></textarea> </div> <input type="checkbox">记住我<br> <div class="input-box"> <button class="button">发布问答</button> </div> </form> </div> {% endblock %}2.6修改密码功能
{% extends'base.html' %}
{% block title %}修改密码{% endblock %} {% block head %} <link rel="stylesheet" type="text/css" href="{ { url_for('static',filename='css/login.css') }}"> <script src="{ { url_for('static',filename='/js/login.js')}}"></script> {% endblock %} {% block main %} <div class="box"> <h2>修改密码</h2> <form action="{ { url_for('updata_password',user_id=user.id) }}" method="post"> <div class="input_box"> oldpwd:<input id="uname" type="text"placeholder="请输入原密码" name="oldpwd"> </div> <div class="input_box"> newpwd:<input id="unickname" type="text"placeholder="请输入新密码" name="newpwd"> </div> <div class="input_box"> newpwd1:<input id="upass" type="password"placeholder="请确认密码" name="newpwd1"> </div> <!--<div class="input_box">--> <!--<a href="{ { url_for('enroll') }}">没有账号?立即注册</a>--> <!--</div>--> <div id="error_box"><br></div> <div class="input_box"> <button class="button" type="submit" οnclick="fnLogin()">登录</button> </div> </form> </div> {% endblock %}
2.7个人中心功能
{% extends "base.html" %}
{% block title %}个人中心{% endblock %} {% block head %} <style> .nav nav-tabs li{ list-style: none; float: left; margin: 25px; } </style> {% endblock %} {% block main %} <h3><span class="glyphicon glyphicon-user" aria-hidden="true"></span>{ { user.username }}</h3> <ul class="nav nav-tabs"> <li role="presentation"><a href="{ { url_for('usercenter',user_id=user.id,tag=1) }}">全部问答</a></li> <li role="presentation"><a href="{ { url_for('usercenter',user_id=user.id,tag=2) }}">全部评论</a></li> <li role="presentation"><a href="{ { url_for('usercenter',user_id=user.id,tag=3) }}">个人信息</a></li> </ul> {% block user %}{% endblock %} {% endblock %}2.8评论功能
{% extends 'user.html' %}
{% block user %} <div class="page-header"> <h3><span class="glyphicon glyphicon-user" aria-hidden="true"></span>{ { username }}<br> <small>全部评论<span class="badge"></span></small> </h3> <ul class="list-group"> {% for foo in comments %} <li class="list-group-item"> <span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span> <a href="{ { url_for('usercenter',user_id=foo.author_id ,tag=2)}}">{ { foo.author.username }}</a> <span class="badge">{ { foo.create_time }}</span> <p>{ { foo.detail }}</p> </li> {% endfor %} </ul> </div> {% endblock %}
2.9个人信息功能
{% extends 'user.html' %}
{% block user %} <div class="page-header"> <h3><span class="glyphicon glyphicon-user" aria-hidden="true"></span>{ { username }}<br> <small>个人信息<span class="badge"></span></small> </h3> <ul class="list-group"> <li class="list-group-item"> {% if user.img %} <img src="/static/{ { user.img }}" alt="" width="150px" height="200px"> {% else %} 无上传图片 {% endif %} <form action="{ { url_for('img',user_id=user.id )}}" method="post" enctype="multipart/form-data"> <input type="file" required name="img"> <button type="submit">上传</button> </form> </li> <li class="list-group-item">用户:{ { user.username }}</li> <li class="list-group-item">编号:{ { user.id }}</li> <li class="list-group-item">昵称:{ { nickname }}</li> <li class="list-group-item">评论次数:{ { comments|length }}</li> <li class="list-group-item">问答次数:{ { questions|length }}</li> <li class="list-group-item"><a href="{ { url_for('updata_password',user_id=user.id) }}">修改密码</a></li> </ul> </div> {% endblock %}
三.数据库设计
3.1注册
function fnEnroll() {
var oZname=document.getElementById("zname"); var oZpass1=document.getElementById("zpass1"); var oZpass2=document.getElementById("zpass2"); var oError=document.getElementById("error_box"); var isError=true; oError.innerHTML="<br>" if ((oZname.value.length < 6) || (oZname.value.length > 12)) { oError.innerHTML = "用户名要6-12位"; isError=false; return isError; }else if ((oZname.value.charCodeAt(0)>=48)&&(oZname.value.charCodeAt(0)<=57)){ oError.innerHTML="首字母必须是字母"; isError=false; return isError; }else for(var i=0;i<oZname.value.length;i++){ if ((oZname.value.charCodeAt(i)<48)||(oZname.value.charCodeAt(i)>57)&&(oZname.value.charCodeAt(i)<97) ||(oZname.value.charCodeAt(i)>122)){ oError.innerHTML="用户名只能是字母和数字"; isNotError=false; return isError; } } if ((oZpass1.value.length < 6) || (oZpass1.value.length > 12)) { oError.innerHTML = "密码要6-12位"; isError=false; return isError; }else if (oZpass1.value!= oZpass2.value) { oError.innerHTML = "两次密码不一致"; isError=false; return isError; } return isError; window.alert("注册成功!") }
3.2登录
function fnLogin() {
var oUname=document.getElementById("uname"); var oUpass=document.getElementById("upass"); var oError=document.getElementById("error_box"); var isError=true; oError.innerHTML="<br>" //uname if ((oUname.value.length < 6) || (oUname.value.length > 20)) { oError.innerHTML = "用户名要6-20位"; isError=false; return isError; }else if ((oUname.value.charCodeAt(0)>=48)&&(oUname.value.charCodeAt(0)<=57)){ oError.innerHTML="首字母必须是字母"; isError=false; return isError; }else { for(var i=0;i<oUname.value.length;i++){ if ((oUname.value.charCodeAt(i)<48)||(oUname.value.charCodeAt(i)>57)&&(oUname.value.charCodeAt(i)<97) ||(oUname.value.charCodeAt(i)>122)){ oError.innerHTML="用户名只能是字母和数字"; isNotError=false; return isError; } } } //upass if ((oUpass.value.length < 6 )|| (oUpass.value.length > 20)) { oError.innerHTML = "密码要6-20位"; isError=false; return isError; } return isError; window.alert("登录成功!") }
3.3其他
function mySwitch() {
var oBody = document.getElementById("myBody"); var oOnOff = document.getElementById("myOnOff"); if (oOnOff.src.match("bulbon")) { oOnOff.src = "http://www.runoob.com/images/pic_bulboff.gif"; oBody.style.background = "black"; oBody.style.color = "white"; } else { oOnOff.src = "http://www.runoob.com/images/pic_bulbon.gif"; oBody.style.background = "white"; oBody.style.color = "black"; } }
四.系统实现的关键算法和数据结构
关键算法是if根据前端传到的数据在后台进行比对,再根据传输的code的值进行判断,再根据js文件的判断,在页面上展示出不同的效果。
其中其code值是如何传输的?这就需要调用其中resful文件中,不同类的定义了。
import os
DEBUG=TrueSECRET_KEY=os.urandom(24) SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:@127.0.0.1:3306/mytest1?charset=utf8'SQLALCHEMY_TRACK_MODIFICATIONS = False
from flask import Flask, render_template, request, redirect, url_for, session,g
from flask_sqlalchemy import SQLAlchemyimport config,osfrom functools import wrapsfrom datetime import datetimefrom sqlalchemy import or_,and_from werkzeug.security import generate_password_hash,check_password_hash app=Flask(__name__) app.config.from_object(config) db=SQLAlchemy(app)# 创建用户模型class User(db.Model): __tablename__ = 'user' id = db.Column(db.Integer,primary_key=True,autoincrement=True) username = db.Column(db.String(20),nullable=False) _password = db.Column(db.String(200),nullable=False)#内部使用 img= db.Column(db.String(200)) nickname=db.Column(db.String(50)) @property def password(self): # 外部使用 return self._password @password.setter def password(self,row_password): self._password = generate_password_hash(row_password) def check_password(self,row_password): result = check_password_hash(self._password,row_password) return result#创建发布问答模型class Question(db.Model): __tablename__ ='questions' id = db.Column(db.Integer, primary_key=True, autoincrement=True) title=db.Column(db.String(100),nullable=False) detail=db.Column(db.Text,nullable=False) create_time=db.Column(db.DateTime,default=datetime.now) fenlei_id = db.Column(db.Integer,db.ForeignKey('fenlei.id')) author_id=db.Column(db.Integer,db.ForeignKey('user.id'))#外键约束,数据类型db.Integer第二个参数指定外键是user表的id author=db.relationship('User',backref=db.backref('questions')) fenlei=db.relationship('Fenlei',backref=db.backref('questions'))# 创建评论模型class Comment(db.Model): __tablename__ = 'comments' id = db.Column(db.Integer, primary_key=True, autoincrement=True) author_id = db.Column(db.Integer, db.ForeignKey('user.id')) questions_id = db.Column(db.Integer, db.ForeignKey('questions.id')) create_time=db.Column(db.DateTime, default=datetime.now) detail=db.Column(db.Text,nullable=False) questions=db.relationship('Question',backref=db.backref('comments',order_by=create_time.desc)) author=db.relationship('User',backref=db.backref('comments'))class Fenlei(db.Model): __tablename__='fenlei' id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(100))class Dianzan(db.Model): __tablename__ = 'dianzan' id = db.Column(db.Integer, primary_key=True, autoincrement=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) # 外键约束,数据类型db.Integer第二个参数指定外键是user表的id questions_id = db.Column(db.Integer, db.ForeignKey('questions.id')) user = db.relationship('User', backref=db.backref('dianzan')) question = db.relationship('Question', backref=db.backref('dianzan'))class Collection(db.Model): __tablename__ = 'collection' id = db.Column(db.Integer, primary_key=True, autoincrement=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) # 外键约束,数据类型db.Integer第二个参数指定外键是user表的id questions_id = db.Column(db.Integer, db.ForeignKey('questions.id')) create_time = db.Column(db.DateTime, default=datetime.now) user = db.relationship('User', backref=db.backref('collection')) question = db.relationship('Question', backref=db.backref('collection')) db.create_all() @app.route('/')def index(): fenleiid= request.args.get('bd',type=int,default=None) if fenleiid: questions = Question.query.filter_by(fenlei_id=fenleiid) else: questions= Question.query.order_by('-create_time').all() context={ "questions":questions, "fenlei":Fenlei.query.all() } return render_template('base.html',**context)#登录@app.route('/login/',methods={ 'GET','POST'})def login(): if request.method=='GET': return render_template('login.html') else: username = request.form.get('username') # 获取form中的数据 password = request.form.get('password') nickname = request.form.get('nickname') user = User.query.filter(User.username == username).first() # id = User.query.filter(User.id == id).first() if user: if user.check_password(password): session['user'] = username session['id'] = user.id session.permanent=True return redirect(url_for('index')) # 返回到首页 else: return u'password error' else: return u'error username or password' #输出错误 #修改密码@app.route('/updata_password/<user_id>',methods={ 'GET','POST'})def updata_password(user_id): if request.method=='GET': return render_template('updata_password.html') else: oldpwd = request.form.get('oldpwd') newpwd = request.form.get('newpwd') newpwd1= request.form.get('newpwd1') user= User.query.filter(User.id==user_id).first() if user.check_password(oldpwd): if newpwd !=newpwd1: return '密码输入不一致' else: user.password=newpwd db.session.commit() return render_template('login.html') else: return '原密码错误'#注册@app.route('/enroll/',methods={ 'GET','POST'})def enroll(): if request.method=='GET': return render_template('enroll.html') else: username=request.form.get('username')# 获取form中的数据 password=request.form.get('password') nickname=request.form.get('nickname') user = User.query.filter(User.username == username).first() if user: return u'username existed' else: user = User(username=username, password=password, nickname=nickname) db.session.add(user)#数据库操作 db.session.commit() return redirect(url_for('login'))# 重定向到登录页 #注销@app.route('/logout/')def logout(): session.clear() return redirect(url_for('index'))# 清除所有数据返回到首页 # 上下文处理器@app.context_processordef mycontext(): usern=session.get('user') userid = session.get('userid') # id=session.get('id') if usern: user = User.query.filter(User.username==usern).first() return { 'username':usern,'user':user, 'userid':user.id } else: return {}# 发布前登录:装饰器def loginFirst(func):# 参数是函数 @wraps(func) def wrapper(*args, ** kwargs):# 定义个函数将其返回 if session.get('user'): return func(*args, ** kwargs) else: return redirect(url_for('login')) return wrapper# 返回一个函数 #提问@app.route('/questions/',methods=['GET','POST']) @loginFirstdef questions(): if request.method == 'GET': fenlei = Fenlei.query.all() return render_template('questions.html',fenlei=fenlei) else: title = request.form.get('title') # 获取form中的数据 detail = request.form.get('detail') fenlei_id = request.form.get('fenlei_id') author_id = User.query.filter(User.username == session.get('user')).first().id questions = Question(title=title, detail=detail, author_id=author_id ,fenlei_id=fenlei_id) db.session.add(questions) # 保存到数据库 db.session.commit() # 提交 return redirect(url_for('index')) # 跳转 # 详情页@app.route('/detail/<questions_id>', methods=['GET', 'POST'])def detail(questions_id): questions = Question.query.filter(Question.id == questions_id).first() # user_id = request.form.get('user_id') dzyes = Dianzan.query.filter( # dzyes用在用户详情页判断是否已点赞的按钮 and_( Dianzan.user_id ==session.get('id'),Dianzan.questions_id == questions.id ) ).first() collection = Collection.query.filter( and_( Collection.user_id ==session.get('id'), Collection.questions_id == questions.id ) ).first() return render_template('detail.html', questions=questions,dzyes=dzyes,collection=collection)#评论页@app.route('/comments/',methods=['POST']) @loginFirstdef comments(): comment=request.form.get('new_comment') questions_id =request.form.get('questions_id') author_id = User.query.filter(User.username == session.get('user')).first().id comments = Comment(detail=comment, author_id=author_id, questions_id=questions_id) db.session.add(comments) # 保存到数据库 db.session.commit() # 提交 return redirect(url_for('detail',questions_id=questions_id))#用户中心页@app.route('/usercenter/<user_id>/<tag>') @loginFirstdef usercenter(user_id,tag): user=User.query.filter(User.id==user_id).first() context={ 'user':user, # 'username':user.username, 'questions':user.questions, 'comments':user.comments } if tag=='1': return render_template('usercenter1.html',**context) elif tag=='2': return render_template('usercenter2.html',**context) else: return render_template('usercenter3.html',**context) # return render_template('usercenter.html',**context)@app.route('/search/')def search(): qu = request.args.get('q') ques = Question.query.filter( or_( Question.title.contains(qu), Question.detail.contains(qu) ) ) return render_template('base.html',questions=ques)#点赞功能@app.route('/dianzan/',methods=['GET','POST']) @loginFirstdef dianzan(): user_id=request.form.get('user_id') questions_id=request.form.get('questions_id') dianzan=Dianzan(user_id=user_id,questions_id=questions_id) db.session.add(dianzan) db.session.commit() return redirect(url_for('detail',questions_id=questions_id))#收藏功能@app.route('/collection/',methods=['GET','POST']) @loginFirstdef collection(): user_id=request.form.get('user_id') questions_id=request.form.get('questions_id') collection=Collection(user_id=user_id,questions_id=questions_id) db.session.add(collection) db.session.commit() return redirect(url_for('detail',questions_id=questions_id)) @app.route('/img/<user_id>',methods=['GET','POST']) @loginFirstdef img(user_id): user = User.query.filter(User.id == user_id).first() f = request.files['img'] basepath = os.path.dirname(__file__) # 当前文件所在路径 upload_path = os.path.join(basepath, 'static/img', f.filename) # 注意:没有的文件夹一定要先创建,不然会提示没有该路径 f.save(upload_path) user.img = 'img/' + f.filename db.session.commit() return redirect(url_for('usercenter',tag=3,user_id=user.id))if __name__ == '__main__': app.run(debug=True)
from flask import Flask
app = Flask(__name__) @app.route('/')def hello_world(): return 'Hello World!'if __name__ == '__main__': app.run()在此次系统中我们放弃了上下文处理器的选择,而重新选择了一种新的函数方法,g函数,g函数是指每次用户登录都会记录和调用其本用户的的数据内容,不需要在后台重新定义一个视图函数在继承在页面中,减少了代码的冗余。提高了数值传递效率。非常的好用,前后台都可以进行使用,只需在hooks文件中添加
五.成品展示