沿用Python+Flask+Mysql的web建設技術開發網站
1 系統概要說明
1.1 開發目的
閑暇時光想看看電影?我要看些什麽好呢?百度推薦出來的爛片也不在其數,如果有一個真實反映影片的平臺該多好,這就是淘智寶的產生,為電影連續劇愛好人群提供一個可以自由言論的平臺,我喜歡的電影我可以發上去,看看別人是否也會喜歡,綜合評價下來,影視愛好者一定能收獲自己最想看的年度好片。
好片是千人的智慧產生,而不摻雜廣告票房目的,如果我們都看過這部片,評論區交流一下一拍即合,也許我們能夠成為好朋友呢?我看你的個人中心你喜歡的電影我都看過,我們是不是就有說不完的話題了呢?
1.2 需求分析
那麽首先,我們需要註冊一個用戶,用戶名和密碼的長度6-12位為宜,註冊用戶後我們需要登錄上去,最好是去個人中心上傳你的頭像,讓更多人註意到你,然後,就可以開始發布一篇新影評了,發布上去後,根據時間的排序,你的影評很快就會被人看到,他們評論了你的影評,也覺得這部電影很好,就會收藏到收藏夾,下次想看電影的時候翻出來看看,或者是給你點了個贊,但是還沒有特別的喜歡,可能只是你的影評寫的不錯。為了賬戶的安全,我們還可以去個人中心定期修改一下密碼,覺得最近的自拍照很好看,也可以更換頭像讓大家看到。
如果我只是一名遊客,我不想註冊新用戶,那麽我可以去排行榜看看大家到底喜歡什麽電影,如果還是看不出來,我可以去詳情頁下載電子書劇情介紹,覺得不錯再去電影院看。每個人都有自己喜歡的電影類型,可以按分類篩選,如果遊客對一部電影早有耳聞,只想看看評價,那麽在搜索框模糊搜索電影的名字,或者主人公的名字,都能夠搜索出來。
2 網站結構設計
2.1 結構分析
2.2 開發方案及使用技術
目前市場流行影視網站網站,用戶都可以在上面與一起觀看該電影的人分享自己的看法,對於平臺上,更多的數據不是我們產生,而是用戶的上網行為影響到自己所看的內容,我們稱之為人機交互,也就是我們現在所說的WEB2.0開發模式。
前端框架,使用的是DIV+CSS的布局,同時使用了AJAX技術,提高了用戶的體現。
後端框架,使用的是Python的Flask框架,這是一款累輕量框架。適合開發中小型系統,並且可以快速開發。
2.3 功能用法分析
首頁主要包括:
1) 熱門文章。給用戶推薦平臺上,點擊數量最大的前五本書,讓用戶可以了解大家都喜歡什麽樣的書。
2) 文章列表。每一本書的標題、時間、作者、分享還有簡介的摘要也會以一條條的形式顯示在首頁,而且每一秒都會顯示再新的分享,圖片展示方式更容易吸引眼球。
3) 高級搜索。單一的搜索只能找到書中有過的關鍵字,高級搜索可以將多個條件同時錄入進行搜索。
4) 文章分類。以類別分別顯示文章列表。
5) 註冊。新用戶註冊平臺賬號。
6) 登陸。登錄賬號去管理個人中心中的個人信息。
7) 排行版:查看最近都有哪些熱門電影,越多人喜歡的電影你肯定也會喜歡。
詳情頁是指文章點進去後,顯示文章內容的頁面,其中還包括以下:
1) 推薦文章。推薦你喜歡的文章。
2) 評論。表達用戶對這篇文章的看法。
3) 點贊。覺得寫的好,就點個贊吧。
4) 收藏。把你認為好的,以後還會看收藏起來,在我的個人中心,以後還可以點開來看。
5) 下載。下載電子書,劇情先知道。
對於有以登錄的用戶,平臺還提供了個人中心去管理自己的信息:
1) 上傳頭像。用戶可以自定義自己的頭像,默認是一個黑色的頭像,上傳有自己個性的頭像,可以讓別人更加容易記得自己。
2) 修改密碼。為了賬號安全,定期修改密碼。
3) 我的收藏。把你認為好的,以後還會看收藏起來,在我的個人中心,以後還可以點開來看。
4) 我的發布。自己曾經發布過的文章可以再次打開的看,也可以有不對的地方再次編輯。
5) 我的評論。你對別人的評論,可以在這裏看到,也可刪除你認為說法有誤的評論。
3 模塊詳細設計
3.1 註冊
# 註冊
@app.route(‘/register/‘, methods=[‘GET‘, ‘POST‘])
def register():
if request.method
== ‘GET‘:
return render_template(‘register.html‘)
else:
username = request.form.get(‘username‘)
password = request.form.get(‘password‘)
say = request.form.get(‘say‘)
user =
User.query.filter(User.username == username).first()
# 判斷用戶名是否存在
if user:
return u‘
username existed‘
else:
user = User(username=username, password=password, say=say)
db.session.add(user)
db.session.commit()
return redirect(url_for(‘login‘))
3.2 登錄
# 登錄 @app.route(‘/login/‘, methods=[‘GET‘, ‘POST‘]) def login(): if request.method == ‘GET‘: return render_template(‘denglu.html‘) else: usern = request.form.get(‘username‘) passw = request.form.get(‘password‘) user = User.query.filter(User.username == usern).first() # 判斷用戶名是否存在 if user: if user.check_password(passw): session[‘user‘] = usern # 字典鍵值 session[‘userid‘] = user.id session.permanent = True return redirect(url_for(‘index‘)) else: return u‘ password error‘ else: return u‘ username not existed‘ # 判斷是否登陸,有則在導航欄顯示用戶名 @app.context_processor def mycontext(): usern = session.get(‘user‘) user = User.query.filter(User.username == usern).first() if usern: return {‘username‘: usern, ‘user‘: user} else: return {} # 登出,清除session @app.route(‘/logout‘) def logout(): session.clear() return redirect(url_for(‘index‘))
3.3 發布
# 發布前登陸裝飾器 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 # 返回一個函數 #發布問答 1.編寫要求登錄的裝飾器 from functools import wraps def loginFirst(func): #參數是函數 @wraps(func) def wrapper(*args, ** kwargs): #定義個函數將其返回 #要求登錄 return func(*args, ** kwargs) return wrapper #返回一個函數 2.應用裝飾器,要求在發布前進行登錄,登錄後可發布。 @app.route(‘/question/‘,methods=[‘GET‘,‘POST‘]) @loginFirst def question(): #發布前登陸裝飾器 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 # 返回一個函數 3.建立發布內容的對象關系映射。 class Question(db.Model): 4.完成發布函數。 保存到數據庫。 重定向到首頁。 #登陸前驗證,進入評論進入問答頁 @app.route(‘/question/‘,methods=[‘GET‘,‘POST‘]) @loginFirst def question(): if request.method==‘GET‘: return render_template(‘question.html‘) else: title=request.form.get(‘title‘) detail = request.form.get(‘detail‘) author_id = User.query.filter(User.username ==session.get(‘user‘)).first().id question = Question(title=title, detail=detail, author_id=author_id) db.session.add(question)
db.session.commit()
return redirect(url_for(‘index‘))
3.4 條件組合搜索
# 查找 @app.route(‘/search/‘) def search(): qu = request.args.get(‘q‘) c = ‘‘ if request.args.get(‘classflyList‘) == None else request.args.get(‘classflyList‘) t = ‘-creat_time‘ if request.args.get(‘creat_time‘) == None else ‘creat_time‘ if request.args.get( ‘creat_time‘) == ‘0‘ else ‘-creat_time‘ y = ‘‘ if request.args.get(‘year‘) == None else request.args.get(‘year‘) ques = Question.query.filter( or_( Question.xiazai.contains(qu), Question.detail.contains(qu) ), Question.classify.like(‘%‘ + c + ‘%‘), Question.creat_time.like(‘%‘ + y + ‘%‘), ).order_by(t).all() return render_template(‘index.html‘, questions=ques)
# 高級查詢 @app.route(‘/highSearch/‘) def highSearch(): if request.args.get(‘click‘): # 判斷get請求中是否有這個變量傳入值 click = request.args.get(‘click‘) # basic.html中獲取click的限定條數 ques = Question.query.filter( Question.click >= click ).order_by(‘-creat_time‘) # 如果該問題點贊數大於click中指定的數字,則查找出來,放到ques,並把ques賦值給questions(全部問答顯示的列表)顯示出來 return render_template(‘index.html‘, questions=ques) if request.args.get(‘comment‘): # 判斷get請求中是否有這個變量傳入值 comment = request.args.get(‘comment‘) # basic.html中獲取comment的限定條數 com = Question.query.all() # 獲取Question表中的所有問答信息,存到com result = [] # 定義一個空列表result for qu in com: # 如果每一個問答信息中的總評論數大於comment中的評論數,就把內容增加到result列表中 if len(qu.comment) >= int(comment): result.append(qu) # 把列表內容賦值給questions return render_template(‘index.html‘, questions=result)
3.5 收藏
# 收藏 @app.route(‘/col‘, methods=[‘GET‘, ‘POST‘]) @loginFirst def col(): user = User.query.filter(User.id == session.get(‘userid‘)).first() context = { ‘questions‘: user.collection.all(), ‘tj‘: Question.query.all()[0:5], } return render_template(‘collect.html‘, **context)
3.6 修改密碼
# 修改密碼 @app.route(‘/setPassword/<user_id>‘, methods=[‘GET‘, ‘POST‘]) @loginFirst def setPassword(user_id): if request.method == ‘GET‘: if request.args.get(‘info‘): info = request.args.get(‘info‘) else: info = None return render_template(‘editPassword.html‘,info=info) else: user = User.query.filter(User.id == user_id).first() if user: if user.check_password(request.form.get(‘old‘)): user.password = request.form.get(‘new1‘) db.session.commit() info = ‘修改成功‘ else: info = ‘原密碼錯誤‘ return redirect(url_for(‘setPassword‘,user_id=user_id,info=info)) else: info = ‘未知錯誤‘ return redirect(url_for(‘personcenter‘, user_id=user_id, info=info))
3.7 上傳頭像
#上傳頭像 @app.route(‘/uploadLogo/<user_id>‘, methods=[‘GET‘, ‘POST‘]) def uploadLogo(user_id): user = User.query.filter(User.id == user_id).first() edimg = request.files[‘edimg‘] basepath = os.path.dirname(__file__) # 當前文件所在路徑 upload_path = os.path.join(basepath, ‘static/uploads‘, edimg.filename) # 註意:沒有的文件夾一定要先創建,不然會提示沒有該路徑 edimg.save(upload_path) user.image = ‘uploads/‘ + edimg.filename db.session.commit() return redirect(url_for(‘personcenter‘, user_id=user_id));
3.8 評論
# 登陸前驗證,進入評論進入問答頁 @app.route(‘/question/‘, methods=[‘GET‘, ‘POST‘]) @loginFirst def question(): if request.method == ‘GET‘: return render_template(‘question.html‘) else: xiazai = request.form.get(‘xiazai‘) title = request.files[‘title‘] basepath = os.path.dirname(__file__) # 當前文件所在路徑 upload_path = os.path.join(basepath, ‘static/fengmian‘, title.filename) # 註意:沒有的文件夾一定要先創建,不然會提示沒有該路徑 title.save(upload_path) # 存進服務器 detail = request.form.get(‘detail‘) author_id = User.query.filter(User.username == session.get(‘user‘)).first().id classify = request.form.get(‘classify‘) question = Question(title=‘http://127.0.0.1:5000/static/fengmian/‘ + title.filename, xiazai=xiazai, detail=detail, author_id=author_id, classify=classify) # question.author=author_id db.session.add(question) db.session.commit() return redirect(url_for(‘index‘))
4 數據庫設計
4.2 程序模型現實
# 收藏表 Collection = db.Table( ‘collection‘, db.Column(‘id‘, db.Integer, primary_key=True, autoincrement=True), db.Column(‘q‘, db.Integer, db.ForeignKey(‘question.id‘)), # 評論對應的文章的id db.Column(‘u‘, db.Integer, db.ForeignKey(‘user.id‘)), # 收藏用戶的id ) #用戶表 class User(db.Model): __tablename__ = ‘user‘ # 建立一個表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) image = db.Column(db.String(100), default=‘uploads/default_logo.jpg‘) say = db.Column(db.String(50)) collection = db.relationship(‘Question‘, secondary=Collection, backref=db.backref(‘user‘, lazy=‘dynamic‘), lazy=‘dynamic‘) @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 # 建立一表question class Question(db.Model): __tablename__ = ‘question‘ 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) xiazai = db.Column(db.Text, nullable=False) creat_time = db.Column(db.DateTime, default=datetime.now) author_id = db.Column(db.Integer, db.ForeignKey(‘user.id‘)) author = db.relationship(‘User‘, backref=db.backref(‘question‘)) classify = db.Column(db.Enum(‘都市言情‘, ‘青春校園‘, ‘古裝玄幻‘, ‘懸疑驚悚‘), nullable=False) click = db.Column(db.INT, default=0) # 評論表 class Comment(db.Model): __tablename__ = ‘comment‘ # 建立一個表log id = db.Column(db.Integer, primary_key=True, autoincrement=True) author_id = db.Column(db.Integer, db.ForeignKey(‘user.id‘)) question_id = db.Column(db.Integer, db.ForeignKey(‘question.id‘)) creat_time = db.Column(db.DateTime, default=datetime.now) detail = db.Column(db.Text, nullable=False) question = db.relationship(‘Question‘, backref=db.backref(‘comment‘, order_by=creat_time.desc)) author = db.relationship(‘User‘, backref=db.backref(‘comment‘))
5 系統實現的關鍵算法與數據結構
5.1 背景開關燈的實現
運行JavaScript代碼,添加點擊事件,來響應並改變背景的CSS樣式,則達到開關燈的功能。
function mySwitch() { var oBody = document.getElementById("myBody"); var ogood = document.getElementById("mygood"); var oOnOff = document.getElementById("myOnOff"); if (oOnOff.src.match(‘bulbon‘)) { oOnOff.src = "http://www.runoob.com/images/pic_bulboff.gif"; oBody.style.backgroundColor = "black"; oBody.style.color = "white"; ogood.style.display="none"; } else { oOnOff.src = "http://www.runoob.com/images/pic_bulbon.gif"; oBody.style.backgroundColor = "white"; oBody.style.color = "black"; ogood.style.display="block"; } }
5.2 圖片與文件的上傳下載實現
一鍵下載電子書,以txt文件形式保存到你的電腦,更方便快捷下次查看
<span style="width:300px;float:left;margin-top: 230px;margin-left:-235px">電子書下載: <input id="fat-btn" class="btn btn-default" type="button" value=‘Download‘ onclick="location.href=‘{{ url_for(‘download‘,filename=‘static‘,question_id=ques.xiazai) }}‘"></span> # 下載 @app.route(‘/<filename>/<question_id>‘) def download(filename, question_id): quest = Question.query.filter(Question.id == question_id).first() # 從Question表查找出對應的問答id context = { ‘questions‘: Question.query.order_by(‘-creat_time‘).all() } return render_template(‘detail.html‘, **context, ques=quest)
上傳頭像,讓他人更好的認識你
# 上傳頭像 @app.route(‘/uploadLogo/<user_id>‘, methods=[‘GET‘, ‘POST‘]) def uploadLogo(user_id): user = User.query.filter(User.id == user_id).first() edimg = request.files[‘edimg‘] basepath = os.path.dirname(__file__) # 當前文件所在路徑 upload_path = os.path.join(basepath, ‘static/uploads‘, edimg.filename) # 註意:沒有的文件夾一定要先創建,不然會提示沒有該路徑 edimg.save(upload_path) user.image = ‘uploads/‘ + edimg.filename db.session.commit() return redirect(url_for(‘personcenter‘, user_id=user_id));
5.3 修改密碼提示
# 修改密碼 @app.route(‘/setPassword/<user_id>‘, methods=[‘GET‘, ‘POST‘]) @loginFirst def setPassword(user_id): if request.method == ‘GET‘: if request.args.get(‘info‘): info = request.args.get(‘info‘) else: info = None return render_template(‘editPassword.html‘,info=info) else: user = User.query.filter(User.id == user_id).first() if user: if user.check_password(request.form.get(‘old‘)): user.password = request.form.get(‘new1‘) db.session.commit() info = ‘修改成功‘ else: info = ‘原密碼錯誤‘ return redirect(url_for(‘setPassword‘,user_id=user_id,info=info)) else: info = ‘未知錯誤‘ return redirect(url_for(‘personcenter‘, user_id=user_id, info=info)) 頁面中:通過定義info提示框實現在後臺應用js代碼 <script> {% if info %} alert(‘{{ info }}‘) {% endif %} </script>
6 成品展示
1網站父模板統一布局
2註冊、登錄、註銷
點擊註銷,呈現的內容不一樣,收藏夾需要登錄前驗證
3.發布引用編輯插件、影評列表div+css顯示
4.詳情頁
夜晚開啟護眼模式:
5.評論、列表顯示
6.個人中心
我對這個作者有興趣,我想看看她的資料(用戶中心):
7.搜索,條件組合搜索
Eg:這是點贊數10以上、評論2以上的
8.文章分類、顯示(古裝玄幻類為例)
9點贊、收藏
Eg:點了個贊變成27:
Eg:沒收藏的時候是這樣的:
Eg:收藏後是這樣的:
10修改密碼、頭像、上傳頭像
上傳頭像和預覽如下:
覺得可以就點擊upload就換好頭像
11我的發布、點贊、收藏、評論
我發過的影評在這裏(可刪除自己的影評):
我發過的評論在這裏(可刪除自己的評論):
收藏過的影評:
12高級搜索
可同時按分類按時間排序:
13熱門文章、推薦文章
推薦的作品在詳情頁可以看到:
熱門的作品在排行榜可以看到:
14下載文件
點擊電子書下載,可以下載到我的電腦
沿用Python+Flask+Mysql的web建設技術開發網站