1、系统概要说明javascript
1.1需求分析html
(1)系统设计的目标前端
系统的首要目标就是可用性,本系统是一个关于书评的网站,可以展现每位读者的书评以及发表书评,为各位用户提供各类书籍的书评以及读书心得,正所谓一千我的的眼里有一千个哈姆雷特,也是对读书的精华浓缩,集思广益,提升阅读的质量和氛围;java
(2)系统设计的简易性python
系统面向的用户主要为普通用户,所以在操做性方面应该尽量的简单,下降复杂性以防止用户不会操做的问题,同时操做简易也会让用户以为系统容易使用,提升普及度。因此系统应该拥有简洁的界面、方便的菜单列表以及协调的颜色搭配;web
1.2概要说明ajax
书评网站的整体目标是为用户提供一个开放注册的在线阅读读者的读书心得,主要有如下功能:算法
(1)用户注册:用户进入相应的注册界面,输入用户名和密码以后提交页面。 若用户名或密码或者验证码格式输入不正确,系统将提示信息错误;若用户名和密码以及验证码输入正确,系统将转发登陆页面数据库
(2)用户登陆:用户进入相应的登陆界面,输入用户名和密码以后提交页面。 若用户名或密码输入不正确,系统将提示信息错误;若用户名和密码输入正确,系统将转发页面到系统首页。flask
(3)信息浏览:用户在没有登陆的状况下能够对各种书评进行多条件组合查询,只有在登陆的状况下才能够对信息的操做,如对其余读者的书评进行打开详情页,点赞,评论,收藏等;
(4)用户资料功能:用户可以注册,登陆,注销,可以发布书评,查看我的资料,修改密码,上传头像,修改头像;
(5)信息推荐:可以推送热门的文章;
2、网站结构设计
网站使用了母板跟子页面的形式,母板页有顶部导航栏,跟底部footer,子因此子页都会带有母板的这两部分。导航栏包括论坛首页、全部书评、热门书评、书评发表、热门书籍推荐、搜索功能、登陆和注册。
登陆以后能够点击用户名进入到我的中心,里面有上传头像,修改密码,修改我的信息等功能。
3、模块详细设计
1.首页
首页属于前端模块,在apps/front目录下的views.py文件也就是视图那里定义了了首页的方法,在首页咱们要展现用户发布过的帖子,因此就要获取到帖子的信息,将数据传到html页面,再在首页的html进行显示,下面是代码。
@bp.route('/')
def index():
board_id = request.args.get('bd',type=int,default=None)
page = request.args.get(get_page_parameter(),type=int, default=1)
boards = BoardModel.query.all()
start =(page-1)*config.PER_PAGE
end = start + config.PER_PAGE
total = 0
query_obj=PostModel.query.order_by(PostModel.create_time.desc())
if board_id:
query_obj = query_obj.filter_by(board_id=board_id)
posts = query_obj.slice(start,end)
total = query_obj.count()
else:
posts = query_obj.slice(start,end)
total = query_obj.count()
pagination = Pagination(bs_version=3,page=page,total=total,outer_window=0,inner_window=2)
context={
'boards': boards,
'posts':posts,
'pagination':pagination,
'current_board':board_id
}
return render_template('front/front_index.html',**context)
2.帖子发布模块
帖子的发布前提是用户已经登陆,因此在后台要定义一个@login required装饰器,装饰器的内容定义在decorator.py文件里面,它根据页面上有没有用户的session ID值来判断用户是否登陆,若是没有就返回登陆页面,若是有的话就能够执行相关操做。
def login_required(func):
@wraps(func)
def inner(*args,**kwargs):
if config.FRONT_USER_ID in session:
return func(*args,**kwargs)
else:
return redirect(url_for('front.signin'))
return inner
帖子发布的设计用到AJAX异步请求的方法,Ajax 是一种用于建立快速动态网页的技术。
Ajax 是一种在无需从新加载整个网页的状况下,可以更新部分网页的技术。
经过在后台与服务器进行少许数据交换,Ajax 可使网页实现异步更新。这意味着能够在不从新加载整个网页的状况下,对网页的某部分进行更新。
在发布帖子的时候先去到表单文件进行板块的判断,若是没有这个板块就会阻止表单的提交,若是判断正确就会将发布的内容提交添加进数据库,并返回发布成功的页面提示。
#发布帖子
@bp.route('/apost/',methods=['GET','POST'])
@login_required
def apost():
if request.method == 'GET':
boards = BoardModel.query.all()
return render_template('front/front_apost.html', boards=boards)
else:
form = AddPostForm(request.form)
if form.validate():
title = form.title.data
content = form.content.data
board_id = form.board_id.data
board = BoardModel.query.get(board_id)
if not board:
return restful.params_error(message='没有这个板块!')
post = PostModel(title=title, content=content)
post.board = board
post.author= g.front_user
db.session.add(post)
db.session.commit()
return restful.success()
else:
return restful.params_error(message=form.get_error())
3。搜索
搜索功能经过在页面上获取输入框所输入的值而后使用上下文context将值放到里面去,在页面进行循环,若是有这个关键字就进行显示,不然不展现。
#搜索功能
@bp.route('/search/')
def search():
qu = request.args.get('q')
ques = PostModel.query.filter(
and_(
PostModel.title.contains(qu)
)
).order_by('-create_time')
board_id = request.args.get('bd', type=int, default=None)
page = request.args.get(get_page_parameter(), type=int, default=1)
boards = BoardModel.query.all()
start = (page - 1) * config.PER_PAGE
end = start + config.PER_PAGE
total = 0
query_obj = PostModel.query.order_by(PostModel.create_time.desc())
if board_id:
query_obj = query_obj.filter_by(board_id=board_id)
posts = query_obj.slice(start, end)
total = query_obj.count()
else:
posts = query_obj.slice(start, end)
total = query_obj.count()
pagination = Pagination(bs_version=3, page=page, total=total, outer_window=0, inner_window=2)
context = {
'boards': boards,
'posts': ques,
'pagination': pagination,
'current_board': board_id
}
4.登陆、注册和注销
登陆功能主要进行的是查询操做,在登陆的时候进行查询,若是有这个用户就进一步判断密码对不对应,若是都对应就登陆成功而且跳转到指定页面。注册功能进行的是查询跟插入的操做,用户输入注册帐号,先去表单判断这个用户名是否存在,若是用户名存在则返回错误信息,若是用户不存在则说明这个用户名能够注册,而后再将用户输入的帐户跟密码提交到数据库完成帐户的添加。注销实现就是将用户登陆以后页面的session值删掉,并跳转到首页。
#注销
@bp.route('/logout/')
@login_required
def logout():
del session[config.FRONT_USER_ID]
return redirect(url_for('front.index'))
#注册功能后台视图
class SignupView(views.MethodView):
def get(self):
return_to = request.referrer
if return_to and return_to != request.url and safeutils.is_safe_url(return_to):
return render_template('front/front_signup.html',return_to=return_to)
else:
return render_template('front/front_signup.html')
def post(self):
form = SignupForm(request.form)
if form.validate():
email = form.email.data
username = form.username.data
password = form.password1.data
user = FrontUser(email=email,username=username,password=password)
db.session.add(user)
db.session.commit()
return restful.success()
else:
print(form.get_error())
return restful.params_error(message=form.get_error())
#登陆功能后台视图
class SigninView(views.MethodView):
def get(self):
return_to = request.referrer
if return_to and return_to != request.url and return_to != url_for("front.signup") and safeutils.is_safe_url(
return_to):
return render_template('front/front_signin.html', return_to=return_to)
else:
return render_template('front/front_signin.html')
def post(self):
form =SigninForm(request.form)
if form.validate():
email = form.email.data
password = form.password.data
remember = form.remeber.data
user = FrontUser.query.filter_by(email=email).first()
if user and user.check_password(password):
session[config.FRONT_USER_ID]=user.id
if remember:
session.permanent= True
return restful.success()
else:
return restful.params_error(message='邮箱或密码错误!')
else:
return restful.params_error(message=form.get_error())
5.我的中心页面
我的中心页面获取用户ID而后根据这个ID再获取到这个用户的其余信息,将其放到context而后再将它显示在前端页面
#我的中心
@bp.route('/usercenter/<user_id>/<tag>')
@login_required
def usercenter(user_id,tag):
user = FrontUser.query.filter(FrontUser.id==user_id).first()
posts = PostModel.query.filter(PostModel.author_id == user_id).all()
collection = CollectionModel.query.filter(CollectionModel.user_id ==user_id).all()
context = {
'user':user,
'posts':posts,
'collection':collection
}
if tag == '1':
return render_template('front/front_usercenter.html',**context)
if tag == '2':
return render_template('front/front_user_apost.html',**context)
else:
return render_template('front/front_user_collection.html',**context)
6.点赞与收藏
#点赞功能
@bp.route('/dianzan/',methods=['GET','POST'])
@login_required
def dianzan():
user_id=g.front_user.id
post_id=request.form.get('post_id')
dianzan=DianzanModel(user_id=user_id,post_id=post_id)
db.session.add(dianzan)
db.session.commit()
return redirect(url_for('front.post_detail',post_id=post_id))
#收藏功能
@bp.route('/collection/',methods=['GET','POST'])
@login_required
def collection():
user_id=g.front_user.id
post_id=request.form.get('post_id')
collection=CollectionModel(user_id=user_id,post_id=post_id)
db.session.add(collection)
db.session.commit()
return redirect(url_for('front.post_detail',post_id=post_id))
点赞与收藏都是经过获取到点赞者的ID而后经过标的联系将数据插入到点赞表跟收藏表之中,显示的时候就经过显示这个用户ID的记录的总和来展现有多少我的点赞或者收藏。
4、数据库设计
在这个系统中我设计了六个表,用户表、点赞表、帖子表、评论表、收藏表、板块表。表的设计在models.py里面完成,并无将其放到运行的py文件里面,放到models.py里面有很大的好处,将模型分离能够方便数据库的使用,可维护性比较高。须要增长表的话在model.py里面定义而后再去输入命令就能够更新表。
class BoardModel(db.Model):
__tablename__='board'
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
name = db.Column(db.String(20),nullable=False)
create_time = db.Column(db.DateTime,default=datetime.now)
class PostModel(db.Model):
__tablename__ ='post'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(200),nullable=False)
content = db.Column(db.Text,nullable=False)
create_time = db.Column(db.DateTime,default=datetime.now)
board_id = db.Column(db.Integer,db.ForeignKey("board.id"))
author_id = db.Column(db.String(100),db.ForeignKey("front_user.id"),nullable=False)
author = db.relationship("FrontUser",backref="posts")
board=db.relationship("BoardModel",backref="posts")
class CommentModel(db.Model):
__tablename__='comment'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
content = db.Column(db.Text,nullable=False)
create_time = db.Column(db.DateTime,default=datetime.now)
post_id = db.Column(db.Integer,db.ForeignKey("post.id"),nullable=False)
author_id = db.Column(db.String(100),db.ForeignKey("front_user.id"),nullable=False)
post = db.relationship("PostModel",backref='comments')
author = db.relationship("FrontUser",backref='comments')
class DianzanModel(db.Model):
__tablename__ = 'dianzan'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
post_id = db.Column(db.Integer, db.ForeignKey("post.id"), nullable=False)
user_id = db.Column(db.String(100), db.ForeignKey("front_user.id"), nullable=False)
post = db.relationship("PostModel", backref=("dianzan"))
user = db.relationship("FrontUser", backref=("dianzan"))
class CollectionModel(db.Model):
__tablename__ = 'collection'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
user_id = db.Column(db.String(100), db.ForeignKey("front_user.id"), nullable=False)
post_id = db.Column(db.Integer, db.ForeignKey("post.id"), nullable=False)
create_time = db.Column(db.DateTime, default=datetime.now)
post = db.relationship("PostModel", backref=("collection"))
user = db.relationship("FrontUser", backref=("collection"))
在表的联系方面合理定义主键外键,使得我么么可使用一个表的主键跟外键的联系得到另外一个表的信息,就实现了能够根据用户ID 来查看他所发表的帖子这一类的功能。
5、成品展现
首页界面:
登陆与注册界面:
帖子发布界面:
帖子详细页面:
搜索功能:
我的中心:
修改信息页面:
密码修改页面:
头像修改:
分页功能:
6、心得体会
经过此次的课程设计,我对flask框架的python web设计有了更深一层的了解。在此次的课程设计中使用了AJAX,Ajax至关于在用户和服务器之间加了—个中间层,使用户操做与服务器响应异步化。并非全部的用户请求都提交给服务器,像—些数据验证和数据处理等都交给Ajax引擎本身来作, 只有肯定须要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求。
Ajax的原理简单来讲经过XmlHttpRequest对象来向服务器发异步请求,从服务器得到数据,而后用javascript来操做DOM而更新页面。这其中最关键的一步就是从服务器得到请求数据。要清楚这个过程和原理,咱们必须对 XMLHttpRequest有所了解。
XMLHttpRequest是ajax的核心机制,它是在IE5中首先引入的,是一种支持异步请求的技术。简单的说,也就是javascript能够及时向服务器提出请求和处理响应,而不阻塞用户。达到无刷新的效果。
Ajax的使用大大提升了数据的传输速度,使得数据不堵塞,使得整个系统使用起来更加的流畅。
一个好的网站是要经过不少次的维护与完善才能作出来的,还有不少的算法以及一些类库的使用我不是很熟练,对于熟练掌握这门技术仍是有比较大的距离,我会继续提升本身的学习能力,把这项技术继续学习到精通,为未来发展打下好的基础。