在一學期裏咱們學習並實現了基於Python的Flask框架web建設項目,要在一學期裏入門一個新的語言而且完成相應的框架項目建,對我這個代碼「小白」來講仍是很是有難度的。css
首先讓咱們來了解一下Python的一些優點和目前的發展狀況,python是一種面向對象的解釋型計算機程序設計語言,語法簡潔清晰,目前已超越java成爲最熱門的編程語言之一。做爲之後有可能向IT方向發展的學生來講,緊跟潮流進行學習和自我提高是很是重要的事情,也許老師也是考慮到這一點,因此讓咱們接觸了最新最熱門的Python以及Pycharm開發工具。html
學期初始,咱們學習了Python的基礎語法,輸入、輸出、交互、數字計算的方法、字符串基本操做、凱撒密碼、自制九九乘法表、中英文詞頻統計等,還學習了import turtle庫,並利用這個庫繪製出多種多樣的圖形,海龜圖標有趣可愛,課堂氛圍活潑許多,從而激發了咱們學習Python的興趣,提高了咱們對編程語言的思惟能力,爲構建Flask框架製做網頁的學習打下基礎。前端
在學習Python+Flask+MysqL的web建設時,須要安裝數據庫(mysql)、開發工具(pycharm)和開發須要用到的第三方庫等。java
一開始,咱們學習網頁前端的製做,第一次知道五花八門的網頁原來是由許許多多的標籤對組成的,每一對都有它特定的一些功能,包含了標籤對裏的衆多參數,每一個參數都有不一樣的含義,給頁面前端帶來不一樣的效果。剛開始接觸html+css+js的時候會想各類辦法去把網頁作好看,嘗試了各類各樣的樣式和標籤對,或者從網頁上cope別人作好的樣式代碼去修改,碰到不會的代碼就問百度解答或同窗探討,在這過程當中又學會了許多課堂上沒有教過的知識,可是最終作出的頁面也不盡人意,這才感悟作出漂亮好看的前端如此不易。老師在課上推薦了菜鳥教程這個平臺(http://www.runoob.com/),裏面的bookstrap樣式簡潔明瞭,非常好看,爲咱們作出一個好看的頁面提供了便捷的途徑。python
在後端建設過程當中,咱們引入了flask庫,用於建立一個Flask對象以及頁面的跳轉,引入flask_sqlalchemy庫進行數據庫的關聯映射等,學習了對數據的增刪改查等操做,利用對數據庫的查詢、添加功能實現了頁面的登錄、註冊以及發佈功能,這些功能的實現根據前端頁面的name屬性名,後臺請求接收同名name的值,再對接收到的值作一系列的操做。在對這些name屬性命名時,要注意先後端對應,且同一頁面不能出現相同命名,不然會出現數據傳遞出錯,形成一系列的麻煩,因此在編程過程當中要時刻注意代碼的惟一性、對應性、儘可能用更少更優化的代碼實現功能。mysql
說到代碼,講了惟一性和對應性,就不得不提簡潔性和清晰性了,打代碼時能夠多用「Ctrl+Alt+L」快捷鍵進行格式化代碼,以便咱們清晰的觀察和修改代碼。養成良好的習慣還在於多用「Ctrl+/」打註釋,把我的的理解和思路整理成簡單的註釋,不只方便本身複習和修改還有利於使用者及他人查看學習。jquery
通常來講,在着手寫代碼前,應先明確目標和功能,理請原理和思路,再開始編寫,遵循小步快走的原則,在寫好每一個功能代碼後,按原理檢查是否出錯, 再運行頁面驗證功能,如此漸漸的把整個系統實現。出錯時也沒必要驚慌,先用F12打開頁面控制檯查看數據發送、接收狀況和紅色報錯項目,或者到pycharm後臺裏找相應的報錯字眼、提示等等去解決問題。web
總之,借用老師的一句話,「編程是一門藝術活」,像作建築通常,字母是它的鋼筋水泥和磚塊,只有實打實的基礎,地基牢固,才能成就崛起的名勝古蹟。sql
本學期學習了python+flask web開發,我覺的本身真正的學到了東西,從菜鳥到會獨立完成本身的項目,過程當中遇到不少問題,查閱資料,與同窗討論後一塊兒解決。 雖然這個學期python課程學習結束了,可是個人學習不會止於此,我還會繼續學習python語言,不斷提高本身的能力。數據庫
工具:pycharm64.exe + Python 3.6 64-bit + MySQL + Navicat for MySQL
(1)導航條
(2)登陸頁面
(3)註冊頁面
(4)發佈頁面
(5)首頁
(6)評論頁面
(7)我的頁面
主py文件:
config:數據庫鏈接
app = Flask(__name__) app.config.from_object(config) db = SQLAlchemy(app) class User(db.Model): # 建立類User __tablename__ = 'user' # 類對應的表名user id = db.Column(db.Integer, primary_key=True, autoincrement=True) # autoincrement自增加 username = db.Column(db.String(20), nullable=False) # nullable是否爲空 _password = db.Column(db.String(200), nullable=False) #內部使用 nickname = db.Column(db.String(20), nullable=True) @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 Fabu(db.Model): __tablename__ = 'fabu' 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) 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('fabu')) class Comment(db.Model): __tablename__ = 'comment' id = db.Column(db.Integer, primary_key=True, autoincrement=True) author_id = db.Column(db.Integer,db.ForeignKey('user.id')) fabu_id = db.Column(db.Integer, db.ForeignKey('fabu.id')) creat_time = db.Column(db.DateTime, default=datetime.now) detail = db.Column(db.Text, nullable=False) fabu = db.relationship('Fabu',backref=db.backref('comments',order_by=creat_time.desc)) author = db.relationship('User', backref=db.backref('comments')) db.create_all() # 使用裝飾器,設置路徑與函數之間的關係。 #使用Flask中render_template,用不一樣的路徑,返回首頁、登陸員、註冊頁。 # 用視圖函數反轉獲得URL,url_for(‘login’),完成導航裏的連接。 @app.route('/') def daohang(): context={ 'fabus': Fabu.query.order_by('-creat_time').all() } return render_template('daohang.html',**context) if __name__ == '__main__': app.run(debug=True)
# 插入功能 user = User(username='15',password='12') db.session.add(user) db.session.commit() # 查詢功能 user=User.query.filter(User.username=="15").first() print(user.username,user.password) # 修改功能 user=User.query.filter(User.username=="15").first() user.password='888' db.session.commit() # 刪除功能 user=User.query.filter(User.username=="15").first() db.session.delete(user) db.session.commit()
url_for運用:
from flask import url_for
跳轉後端請求:
加載靜態文件:(css、js、image)
繼承父模板:
(1)html文件:
{% extends 'daohang.html' %} {% block zhucetitle %}註冊{% endblock %} {% block zhucehead %} <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='css/denglu.css') }}"> <script src="{{ url_for('static',filename='js/denglu.js') }}"></script> {% endblock %} {% block daohangbody %} <div class="center-block" id="zhucebox"> <div class="panel panel-primary" id="zhucebox1_1"> <div class="panel-heading"> <h2 class="panel-title">註冊</h2> </div> <br> <form class="bs-example bs-example-form" role="form" action="{{ url_for('zhuce') }}" method="post"> <div class="input-group"> <span class="input-group-addon"></span> <input type="text" class="form-control" name="user" id="user" placeholder="請輸入用戶名"> </div> <br> <div class="input-group"> <span class="input-group-addon"></span> <input type="password" class="form-control" name="pass" id="pass" placeholder="請設置密碼" > </div> <br> <div class="input-group"> <span class="input-group-addon"></span> <input type="password" class="form-control" id="again" placeholder="請再次輸入密碼"> </div> <div id="error_box1"> <br> </div> <br> <label><input type="submit" class="btn btn-default" value="註冊" onclick="fnRegistration()"></input></label> </form> </div> </div> {% endblock %}
(2)js文件:
function fnRegistration() { var uSer = document.getElementById("user"); var pAss = document.getElementById("pass"); var aGain = document.getElementById("again"); var oError = document.getElementById("error_box"); var isError = true; oError.innerHTML = "<br>"; // 驗證用戶名 if (uSer.value.length < 6 || uSer.value.length > 20) { oError.innerHTML = "用戶名只能6-20位"; isError = false; return isError; } else if ((uSer.value.charCodeAt(0) >= 48) && (uSer.value.charCodeAt(0) <= 57)) { oError.innerHTML = "用戶名首字母不能是數字"; isError = false; return isError; } else for (var i = 0; i < uSer.value.length; i++) { if ((uSer.value.charCodeAt(i) < 48) || (uSer.value.charCodeAt(i) > 57) && (uSer.value.charCodeAt(i) < 97) || (uSer.value.charCodeAt(i) > 122)) { oError.innerHTML = "用戶名只能由數字和字母組成"; isError = false; return isError; } } // 驗證密碼 if (pAss.value.length < 6 || pAss.value.length > 20) { oError.innerHTML = "密碼只能6-20位"; isError = false; return isError; } // 驗證再次輸入的密碼 if (aGain.value != pAss.value) { oError.innerHTML = "密碼不一致"; isError = false; return isError; } // 驗證彈框 window.alert("註冊成功!"); return true; }
(3)py文件:
@app.route('/zhuce/', methods=['GET', 'POST']) def zhuce(): if request.method == 'GET': return render_template('zhuce.html') else: username = request.form.get('user') # post請求模式,安排對象接收數據 password = request.form.get('pass') nickname = request.form.get('nickname') user = User.query.filter(User.username == username).first() # 做查詢,並判斷 if user: return u'該用戶已存在' else: user = User(username=username, password=password, nickname=nickname) # 將對象接收的數據賦到User類中,即存到數據庫 db.session.add(user) # 執行操做 db.session.commit() return redirect(url_for('denglu')) # redirect重定向
(1)html文件:
{% extends 'daohang.html' %} {% block denglutitle %}登錄{% endblock %} {% block dengluhead %} <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='css/denglu.css') }}"> <script src="{{ url_for('static',filename='js/denglu.js') }}"></script> {% endblock %} {% block daohangbody %} <div class="center-block" id="loginbox"> <div class="panel panel-primary" id="loginbox1_1"> <div class="panel-heading"> <h2 class="panel-title">登錄</h2> </div> <br> <form class="bs-example bs-example-form" role="form" action="{{ url_for('denglu') }}" method="post"> <div class="input-group"> <span class="input-group-addon"></span> <input class="form-control" type="text" name="user" id="user" placeholder="請輸入用戶名"> </div> <br> <div class="input-group"> <span class="input-group-addon"></span> <input class="form-control" type="password" name="pass" id="pass" placeholder="請輸入密碼" > </div> <div id="error_box"> <br> </div> <div class="checkbox"> <label> <input type="checkbox">記住我 </label> </div> <br> <label><input type="submit" class="btn btn-default" onclick="fnLogin()" value="登錄"> </input> </label> </form> </div> </div> {% endblock %}
(2)js文件:
function fnLogin() { var uSer = document.getElementById("user"); var pAss = document.getElementById("pass"); var oError = document.getElementById("error_box"); var isError = true; oError.innerHTML = "<br>"; // 驗證用戶名 if (uSer.value.length < 6 || uSer.value.length > 20) { oError.innerHTML = "用戶名只能6-20位"; isError = false; return isError; } else if ((uSer.value.charCodeAt(0) >= 48) && (uSer.value.charCodeAt(0) <= 57)) { oError.innerHTML = "用戶名首字母不能是數字"; isError = false; return isError; } else for (var i = 0; i < uSer.value.length; i++) { if ((uSer.value.charCodeAt(i) < 48) || (uSer.value.charCodeAt(i) > 57) && (uSer.value.charCodeAt(i) < 97) || (uSer.value.charCodeAt(i) > 122)) { oError.innerHTML = "用戶名只能由數字和字母組成"; isError = false; return isError; } } // 驗證密碼 if (pAss.value.length < 6 || pAss.value.length > 20) { oError.innerHTML = "密碼只能6-20位"; isError = false; return isError; } // 驗證彈框 window.alert("登錄成功!"); return true; }
(3)py文件:
內有session功能
@app.route('/denglu/', methods=['GET', 'POST']) def denglu(): if request.method == 'GET': return render_template('denglu.html') else: username = request.form.get('user') # post請求模式,安排對象接收數據 password = request.form.get('pass') user = User.query.filter(User.username == username).first() # 做查詢,並判斷 if user: # 判斷用戶名 if user.check_password(password):# 判斷密碼 session['user'] = username # 利用session添加傳回來的值username session.permanent = True # 設置session過時的時間 return redirect(url_for('daohang')) else: return u'用戶密碼錯誤' else: return u'用戶不存在,請先註冊'
處理器模板:
(1)html文件:
{% extends 'daohang.html' %} {% block fabutitle %}發佈{% endblock %} {% block fabuhead %} <link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css"> <script src="http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script> <script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script> {% endblock %} {% block daohangbody %} <style> .center { margin: auto; width: 60%; border: 3px solid #73AD21; padding: 10px; } </style> <div class="panel panel-default center" style="height:450px;width:500px"> <div class="panel-body"> <div class="form-group"> <form role="form" action="{{ url_for('fabu') }}" method="post"> <div class="form-group"> <label for="name" style="color: black">選擇列表</label><br> <select class="form-control" style="height:35px;width:400px"> <option>1</option> <option>2</option> <option>3</option> <option>4</option> <option>5</option> </select> <br> <label for="title" style="color:black">標題</label><br> <textarea class="form-control" rows="1" cols="50" id="title" name="title" style="height:35px;width:400px"></textarea><br> <label for="detail" style="color: black">詳情</label><br> <textarea class="form-control" rows="5" cols="50" id="detail" name="detail" style="height:100px;width:400px"></textarea><br> <input style="color: whitesmoke" type="checkbox" name="c1" id="c1" value="">記住我<br> <div id=""><br></div> <input type="submit" value="發佈" class="btn btn-default" onclick=""> </div> </form> </div> </div> </div> {% endblock %}
(2)py文件:
class Fabu(db.Model): __tablename__ = 'fabu' 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) 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('fabu')) def loginFirst(fabu): @wraps(fabu) # 加上wraps,它能夠保留原有函數的__name__,docstring def wrapper(*args, **kwargs): # 定義wrapper函數將其返回,用*args, **kwargs把原函數的參數進行傳遞 if session.get('user'): # 只有通過登錄,session才能記住並get到值 return fabu(*args, **kwargs) else: return redirect(url_for('denglu')) return wrapper @app.route('/fabu/', methods=['GET', 'POST']) @loginFirst def fabu(): if request.method == 'GET': return render_template('fabu.html') else: title = request.form.get('title') detail = request.form.get('detail') author_id = User.query.filter( User.username == session.get('user')).first().id fabu = Fabu(title=title, detail=detail, author_id=author_id) db.session.add(fabu) db.session.commit() return redirect(url_for('daohang'))
(1)html文件:
{% extends 'daohang.html' %} {% block fabu_viewtitle %}發佈{% endblock %} {% block fabu_viewhead %} <link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css"> <script src="http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script> <script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script> {% endblock %} {% block daohangbody %} <h2 href="#" class="text-center" style="color: oldlace">{{ ques.title }}</h2> <br> <p class="text-center"> <a href="#"> <small>{{ ques.author.username }}</small> </a>    <span class="pull-center" style="color: oldlace"><small>{{ ques.creat_time }}</small></span> </p> <hr> <div style="width: 700px;margin: auto"> <p style="color: oldlace">{{ ques.detail }}</p> </div> <hr> <form action="{{ url_for('comment') }}" method="post"> <div class="form-group" style="height: 180px;width: 700px;margin: auto"> <textarea name="pinglun" class="form-control" rows="5" id="pinglun" placeholder="請輸入評論"></textarea> <input type="hidden" name="hidden_id" value="{{ ques.id }}"> <br> <input type="submit" value="發送" class="btn btn-default" onclick=""> </div> <div style="width: 700px;margin: auto"> <h4 style="color: oldlace">評論:({{ ques.comments|length }})</h4> <ul class="list-unstyled"> {% for foo in comments %} <li class="list-group-item"> <a>{{ foo.author.username }}</a> <span class="badge pull-right">{{ foo.creat_time }}</span> <p>{{ foo.detail }}</p> <br> </li> {% endfor %} </ul> </div> </form> {% endblock %}
(2)py文件:
class Comment(db.Model): __tablename__ = 'comment' id = db.Column(db.Integer, primary_key=True, autoincrement=True) author_id = db.Column(db.Integer,db.ForeignKey('user.id')) fabu_id = db.Column(db.Integer, db.ForeignKey('fabu.id')) creat_time = db.Column(db.DateTime, default=datetime.now) detail = db.Column(db.Text, nullable=False) fabu = db.relationship('Fabu',backref=db.backref('comments',order_by=creat_time.desc)) author = db.relationship('User', backref=db.backref('comments')) @app.route('/detail/<question_id>') def detail(question_id): quest=Fabu.query.filter(Fabu.id==question_id).first() comments = Comment.query.filter(Comment.fabu_id == question_id).all() return render_template('fabu_view.html',ques=quest,comments=comments) @app.route('/comment/',methods=['POST']) @loginFirst def comment(): detail = request.form.get('pinglun') author_id = User.query.filter(User.username == session.get('user')).first().id fabu_id = request.form.get('hidden_id') comment = Comment(detail=detail,author_id=author_id,fabu_id=fabu_id) db.session.add(comment) # 執行操做 db.session.commit() # 提交到數據庫 return redirect(url_for('detail',question_id=fabu_id))
html文件:
(1)user模板:
{% extends 'daohang.html' %} {% block title %}我的中心{% endblock %} {% block head %} {% endblock %} {% block daohangbody %} <div style="width: 700px;margin: auto"> <ul class="nav nav-pills "> <li class="active"><a href="{{ url_for('usercenter',user_id=user_id,tag=1) }}">我的信息</a></li> <li class="active"><a href="{{ url_for('usercenter',user_id=user_id,tag=2) }}">所有評論</a></li> <li class="active"><a href="{{ url_for('usercenter',user_id=user_id,tag=3) }}">所有發佈</a></li> </ul> {% block user %}{% endblock %} </div> {% endblock %}
(2)usercenter1:
{% extends 'user.html' %} {% block user %} <div class="page-header"> <ul class="page-header"> <h3 style="color: whitesmoke"><span class="glyphicon glyphicon-user" aria-hidden="true"></span>{{ username }}<br> <small style="color: azure">我的資料信息<span class="badge"></span></small> </h3> <div class="panel panel-default" style="height:180px;width:400px"> <ul class="list-group" style="..."> <li class="list-group-item">用戶名:{{ username }}</li> <li class="list-group-item">暱稱:</li> <li class="list-group-item">性別:</li> <li class="list-group-item">年齡:</li> </ul> </div> </ul> </div> {% endblock %}
(3)usercenter2:
{% extends 'user.html' %} {% block user %} <div class="page-header"> <ul class="page-header"> <h3 style="color: whitesmoke" ><span class="glyphicon glyphicon-user" aria-hidden="true"></span>{{ username }}<br> <small style="color: azure">所有評論<span class="badge"></span></small> </h3> <div class="panel panel-default" style="width:700px"> <ul class="list-group" style="..."> {% 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=1) }}">{{ foo.author.username }}</a> <span class="badge">{{ foo.creat_time }}</span> <p style="...">{{ foo.detail }}</p> </li> {% endfor %} </ul> </div> </ul> </div> {% endblock %}
(4)usercenter3:
{% extends 'user.html' %} {% block user %} <div class="page-header"> <ul class="page-header"> <h3 style="color: whitesmoke"><span class="glyphicon glyphicon-user" aria-hidden="true"></span>{{ username }}<br> <small style="color: azure">所有問答<span class="badge"></span></small></h3> <ul class="list-group" style="height:300px;width:700px"> {% for foo in fabus %} <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=1) }}">{{ foo.author.username }}</a> <span class="badge">{{ foo.creat_time }}</span> <p style="...">{{ foo.detail }}</p> </li> {% endfor %} </ul> </ul> </div> {% endblock %}
py文件:
@app.route('/usercenter/<user_id>/<tag>') @loginFirst def usercenter(user_id,tag): user=User.query.filter(User.id==user_id).first() context={ 'user_id':user.id, 'username': user.username, 'fabus': user.fabu, '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)
@app.route('/search/') def search(): qu = request.args.get('q') ques = Fabu.query.filter( or_( Fabu.title.contains(qu), Fabu.detail.contains(qu) ) ).order_by('-creat_time') return render_template('daohang.html', fabus=ques)
@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