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的使用大大提升了數據的傳輸速度,使得數據不堵塞,使得整個系統使用起來更加的流暢。
一個好的網站是要經過不少次的維護與完善才能作出來的,還有不少的算法以及一些類庫的使用我不是很熟練,對於熟練掌握這門技術仍是有比較大的距離,我會繼續提升本身的學習能力,把這項技術繼續學習到精通,爲未來發展打下好的基礎。