知了课堂网站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
方式提交的表单:
- 传入一个查询参数,利用
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 {}