知了課堂網站demo搭建修改版本記錄:
關系數據庫模型的設置:
- 例如段子內容的網頁,需要設置與
User
表相聯系的外鍵約束,并且設置這個與User
的關系屬性:
author_id = db.Column(db.Integer,db.ForeignKey('user_table.id'))
author = db.relationship('User',backref=db.backref('jokes'))
- 在段子內容的評論模塊當中,要設置與段子內容的數據庫模型,和用戶的數據庫模型,并且設置相對應的關系:
joke_id = db.Column(db.Integer,db.ForeignKey('joke_cont.id'))
user_id = db.Column(db.Integer,db.ForeignKey('user_table.id'))
# 建立關系:
Joke = db.relationship('Joke',backref=db.backref('comments'))
author = db.relationship('User',backref=db.backref('comments'))
- 建立
Joke
這個屬性,可以通過這個屬性來查找這個評論屬于的段子,反轉字段comments
表示查找這個段子所有擁有的評論
注冊功能的完成:
1.提交方式:
- 和登錄功能一樣,當用戶的請求為
GET
請求時,服務器返回渲染好的表單模板;當請求為POST
請求時,依次獲得表單的字段的值:
if request.method == 'GET':
return render_template("regist.html")
else:
tel_num = request.form.get('tel_num')
username = request.form.get('username')
password = request.form.get('password')
password2 = request.form.get('password2')
2.判斷用戶的注冊狀態,存入數據庫:
- 先判斷用戶的用戶名或者手機號是否存在于數據庫中:
user = User.query.filter(User.tel == tel_num).first()
- 如果不存在則再判斷用戶兩次輸入的密碼是否相同:
if user:
return "您的手機號已經注冊,請更換手機號!"
else:
if password != password2:
return "兩次輸入的密碼錯誤,請重新輸入!"
else:
...
- 如果符合注冊的條件就存入數據庫,最后跳轉到登錄的頁面:
...
user = User(tel=tel_num,username=username,password=password)
db.session.add(user)
db.session.commit()
return redirect(url_for("login"))
登錄功能的完成:
1.登錄的提交方式:
- 采用
post
和GET
的提交方式,當用戶第一次請求網頁的時候為GET
的提交方式,
if request.methond == 'GET'
...
- 用
request
的method
的屬性來判斷與用戶的提交方式,當為GET
方式時,返回給用戶渲染好的表單模板
...
return render_template("login.html")
- 當用戶填入表單字段 ,并且提交表單的時候,為
POST
的提交方式;
else:
form_tel = request.form.get('username')
form_password = request.form.get('password')
...
- 用
request
的from.get
的屬性來獲得對應表單name
屬性名的表單字段的值
2.查詢數據庫,檢驗提交的表單值:
- 進行查找數據庫:
...
user = User.query.filter(User.username == form_username,User.password == form_password).first()
...
- 當
user
的模型可以被查找到時,說明用戶存在,并且密碼正確;接下來,保存用戶登錄的session
,并且設置session的user_id
的值為用戶數據庫保存的id
值
...
if user:
session['user_id'] = user.id
session.permanent = True
return redirect(url_for('hello_world'))
注銷功能的完成:
- 注銷的功能是通過刪除用戶的
session
來完成:
session.pop('user_id')
# del session('user_id')
# session.clear('user_id')
- 刪除
session
可通過del
,pop
,clear
的方法刪除session
搜索功能的完成:
1.路由設置:
@app.route('/search/',methods=['GET'])
def search():
...
- 設置一個路由采用
GET
的提交方式,與此對應的前端模板當中采用get
方式提交的表單:
<input type="text" class="form-control" placeholder="Enter search" name="q">
- 傳入一個查詢參數,利用
GET
方式提交的內容進行查找。
2.sqlalchemy的查詢功能:
- 首先通過
request.args.get()
的方法得到表單提交的查詢參數;
q = request.args.get('q')
- 在數據庫中查詢與查詢參數匹配的內容(同時匹配模型的標題和內容):
query_cont = Joke.query.filter(or_(Joke.title.contains(q),Joke.content.contains(q))).all()
在這里,需要導入sqlalchemy
的_or
的屬性:
from sqlalchemy improt _or
利用g對象進行優化代碼:
1.優化查詢:
...
user_id = session.get('user_id')
user = User.query.filter(User.id == user_id).first()
joke.author = user
...
...
user_id = session.get('user_id')
user = User.query.filter(User.id == user_id).first()
comment.author = g.user
...
- 在這里,每次都要獲得
session
的user_id
然后在數據庫查詢獲得user
的模型,通過@app.before_request
在每次請求之前都執行的鉤子函數,將這個user
模型保存到g
屬性當中:
@app.before_request
def my_before_request():
user_id = session.get('user_id')
if user_id:
user = User.query.filter(User.id == user_id).first()
# 綁定全局對象g:
g.user = user
- 綁定在
g
全局對象之后,可以直接通過g.user
訪問通過user_id
查詢到的user
模型
2.優化上下文處理器的鉤子函數:
- 在加入
@app.before_request
的鉤子函數之后,請求之前的操作為:before_request
——視圖函數
——context_processor
@app.context_processor
def my_context_prossor():
user_id = session.get('user_id')
if user_id:
user = User.query.filter(User.id == user_id).first()
if user:
return {'user':user}
return {}
- 在
context_processor
中,也進行了數據庫的查詢操作,將降低網頁加載的速度,這就可以用過g.user
來優化代碼:
...
user_id = session.get('user_id')
# hasattr方法判斷g對象是否有user屬性,如果有user屬性,則代表用戶已經登錄:
if hasattr(g,'user'):
return {'user':g.user}
return {}