知了课堂网站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 {}