- 个人学期总结
- 总结Python+Flask+MysqL的web建设技术过程,标准如下:
- 即是对自己所学知识的梳理
- 也可作为初学入门者的简单教程
- 也可作为自己以后复习的向导
- 也是一种向外展示能力的途径
一、个人学期总结
在这个学期里,我通过学校课程学习了Python+Flask+MysqL的web建设技术。一开始我们学的是简单的基本语法和输出输入,学习了用turtle库绘制出图形,学习了字符串基本操作、凯撒密码、自制九九乘法表、中英文词频统计等等,虽然语句都挺简单的,但也是为了以后开发web做准备。到真正进入web开发时,我们首先安装了pycharm、MySQL和一些python的第三方库,接着首先老师教了我们网页前端的制作,页面的排版分布,设计了简单的布局。第一次知道原来网页原来是div块组成的,而且可以通过class值或id值来设计css样式布置结构,还能编写js代码,设置一些权限,也能让按钮实现更多的功能。虽然感觉学起来并不难,但却很繁琐,比如在布置div块的位置的时候,很多时候是一个值一个值去试的,还有很多属性值要自己再额外去查找,编写过程中也要细心谨慎。随后学习了很多功能的实现,比如登录注册搜索发布。最主要的就是连接mysql,通过前端文本框将数值存入数据库,最后再调用数据库把想要的结果显示出来,这是最难也是最重要的地方,需要自己用心去记一些语法。通过本次web建设技术的课程,我将这一学期所学的web开发基础的知识用到了具体的实践中去,锻炼了动手实践能力和独立思考的能力,收获了喜悦也收获了失落。在这一个学期里,除了课堂上所教的知识,我也在网上搜索了很多资料,完善自己的前端网页,尽量做到完美,但由于水平有限做出来的还是没能像一些网站一样简洁漂亮,今后还会继续努力,做出更好的网页。
配置环境: python3.5,flask2.0,连接数据库时使用了pymysql,所有使用前应该安装pymysql:pip install pymysql
程序结构:
二、建立mysql和app的连接
在config.py中加入以下两项配置:
import os SECRET_KEY = os.urandom(24) SQLALCHEMY_DATABASE_URI = ‘mysql+pymysql://root:@127.0.0.1:3306/test?charset=utf8‘ SQLALCHEMY_TRACK_MODIFICATTONS = False
import config app.config.from_object(config)
db = SQLAlchemy(app)
class User(db.Model): __tablename__ = ‘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) nickname = db.Column(db.String(20)) @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 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) 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‘)) 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‘)) 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(‘comments‘)) author = db.relationship(‘User‘, backref=db.backref(‘comments‘))
三、完成基本的页面设计
1.导航,头部,CSS基础
<div> <nav class="bar6"> <ul> <li><img src="../static/image/ars.png" width=50px></li> <li><img id="on_off" onclick="mySwitch()" src="http://img2.imgtn.bdimg.com/it/u=1878009223,3806655311&fm=200&gp=0.jpg" width="50px"></li> <li><a href="{{ url_for(‘base‘) }}" >首页</a></li> <li><a href="{{ url_for(‘questions‘) }}">发布问答</a></li> {% if username %} <li><a href="{{ url_for(‘usercenter‘,user_id=session.get(‘userid‘),tag=3) }}" style="margin-right: -10px;color:deepskyblue">{{ session.get(‘user‘) }}</a></li> <li><a href="{{ url_for(‘logout‘) }}" >注销</a></li> <li><a href="{{ url_for(‘change‘) }}" >修改密码</a></li> {% else %} <li><a href="{{ url_for(‘sign_in‘) }}" >登录</a></li> <li><a href="{{ url_for(‘sign_up‘) }}" >注册</a></li> {% endif %} <form action="{{ url_for(‘search‘) }}" method="get"> <li><input name =‘q‘ type="text" style="border-radius: 25px;margin-top: 12px" placeholder="请输入您要搜索的关键字..."> <button type="submit"style="border-radius: 25px;margin-top: 9px"></button></li> </form> </ul> </nav> </div>
结果:
- 认识CSS的 盒子模型。
- CSS选择器的灵活使用。
- 实例:
- 图片文字用div等元素布局形成HTML文件。
- 新建相应CSS文件,并link到html文件中。
- CSS文件中定义样式
- div.img:border,margin,width,float
- div.img img:width,height
- div.desc:text-align,padding
- div.img:hover:border
- div.clearfloat:clear
<div class="container"> <div class="bar7"> <ul> <li><a href="https://baike.baidu.com/item/ARASHI/4106370?fr=aladdin"> <img src="http://p3.so.qhimgs1.com/bdr/_240_/t0109ab8c105af58973.jpg" width="300px"></a> <div class="desc"><a href="{{ url_for(‘base‘) }}"></a>首页</div> </li> <li><a href="https://baike.baidu.com/item/ARASHI/4106370?fr=aladdin"> <img src="http://p0.so.qhimgs1.com/bdr/_240_/t010b57c4173029c22c.jpg" width="300px" ></a> <div class="desc"><a href="https://baidu.com/">联系我们</a></div></li> <li><a href="https://baike.baidu.com/item/ARASHI/4106370?fr=aladdin"> <img src="http://p3.so.qhimgs1.com/bdr/_240_/t0109ab8c105af58973.jpg" width="300px"></a> <div class="desc"><a href="https://baidu.com/">联系我们</a></div> </li> <li><a href="https://baike.baidu.com/item/ARASHI/4106370?fr=aladdin"> <img src="http://p0.so.qhimgs1.com/bdr/_240_/t010b57c4173029c22c.jpg" width="300px" ></a> <div class="desc"><a href="https://baidu.com/">联系我们</a></div> </li> </ul> </div>
css:
.bar7 ul { list-style-type: none; margin: 0; padding: 0; overflow-x: hidden; overflow-y: auto; } .bar7 ul li { float: left; } li a:hover:not(.active) { background-color: orange; } .col-sm-6 { width: 50%; } .row { margin-right: -15px; margin-left: -15px; } .container { width: 1500px; padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } img{ margin:10px; } div.desc{ text-align: center; padding:5px; } div.img:hover{ border: 1px solid #777777; }
结果:
完成登录与注册页面的HTML+CSS+JS,其中的输入项检查包括:
用户名6-12位
首字母不能是数字
只能包含字母和数字
密码6-12位
注册页两次密码是否一致
function myLogin() { var oUname = document.getElementById("uname"); var oPass = document.getElementById("upass"); var oError = document.getElementById("error_box"); var isError = true; oError.innerHTML = "<br>"; if (oUname.value.length < 6 || oUname.value.length > 20) { oError.innerHTML = ‘请输入6-20位的用户名‘; isError = false; return isError; } if (oUname.value.charCodeAt(0) >= 48 && oUname.value.charCodeAt(0) <= 57) { oError.innerHTML = ‘首字母不能为数字‘; return isError; } else for (var i = 0; i < oUname.value.length; i++) { if ((oUname.value.charCodeAt(i) > 122 || oUname.value.charCodeAt(i) < 97) && (oUname.value.charCodeAt(i) > 57 && oUname.value.charCodeAt(i) < 48)) { oError.innerHTML = ‘只能输入字母或数字‘; isNotError = false; return isError; } } if (oPass.value.length < 6 || oPass.value.length > 20) { oError.innerHTML = ‘请输入6-20位的密码‘; return isError; } }
注册js:
function myRegist() { var oUname=document.getElementById("uname"); var oPass=document.getElementById("upass"); var oPas=document.getElementById("upas"); var oError=document.getElementById("error_box"); var isError=true; oError.innerHTML="<br>"; if(oUname.value.length< 6||oUname.value.length> 20){ oError.innerHTML=‘请输入6-20位的用户名‘; isError=false; return isError; } else if(oUname.value.charCodeAt(0)>=48&&oUname.value.charCodeAt(0)<=57){ oError.innerHTML=‘首字母不能为数字‘; return isError; } else for(var i=0;i<oUname.value.length;i++){ if((oUname.value.charCodeAt(i)>122||oUname.value.charCodeAt(i)<97)&&(oUname.value.charCodeAt(i)>57&&oUname.value.charCodeAt(i)<48)){ oError.innerHTML=‘只能输入字母或数字‘; isError=false; return isError; } } if(oPass.value.length<6||oPass.value.length>20){ oError.innerHTML=‘请输入6-20位的密码‘; isError=false; return isError; } if(oPass.value!=oPas.value){ oError.innerHTML=‘密码不一致‘; isError=false; return isError; } window.alert(‘注册成功‘) return isError }
登录html:
<div class="box"> <h2>登录</h2> <form class="form" method="post" action="{{ url_for(‘sign_in‘) }}"> <div class="input_box"> <input id="uname" class="sign" type="text" placeholder="请输入用户名" name="username"> </div> <div class="input_box"> <input id="upass" class="sign" type="password" placeholder="请输入密码" name="password"> </div> <div id="error_box"><br> </div> <div class="input_box"> <input type="submit" name="commit" value="登录" class="sign-in-button" data-disable-with="登录" onclick="return myLogin()"> </div> </form> </div>
注册html:
<div class="box"> <h2>注册</h2> <form action="{{ url_for(‘sign_up‘) }}" method="post"> <div class="input_box"> <input id="uname" class="sign" type="text" placeholder="请输入用户名" name="username"> </div> <div class="input_box"> <input id="unick" class="sign" type="text" placeholder="请输入昵称" name="nickname"> </div> <div class="input_box"> <input id="upass" class="sign" type="password" placeholder="请输入密码" name="password"> </div> <div class="input_box"> <input id="upas" class="sign" type="password" placeholder="请再输入一次密码" name="opassword"> </div> <div id="error_box"><br> </div> <div class="input_box"> <input type="submit" name="commit" value="注册" class="sign-in-button" data-disable-with="注册" onclick="return myRegist()"> </div> </form> </div>
css:
h2{ text-align: center; color:#3194d0; font-size: 20px; } .sign{ width: 100%; height: 50px; margin-bottom: 0; vertical-align: middle; } .box{ width: 300px; height: 155px; margin: 50px auto; margin-top:150px ; } .sign-in-button{ width: 100%; padding: 9px 18px; font-size: 18px; border: none; border-radius: 25px; color: #fff; background: #3194d0; cursor: pointer; outline: none; display: block; clear: both; } .text{ width: 80px; height: 30px; margin-bottom: 0; vertical-align: middle; }
结果:
四、开始flask项目
- from flask import request, redirect, url_for
- @app.route(‘/regist/‘, methods=[‘GET‘, ‘POST’])
def regist():
if request.method == ‘GET‘:
return render_template(‘regist.html‘)
else:
username = request.form.get(‘username’)#获取form中的数据
判断用户名是否存在:存在报错
不存在,存到数据库中
redirect重定向到登录页
@app.route(‘/sign_up/‘,methods=[‘GET‘,‘POST‘]) def sign_up(): if request.method==‘GET‘: return render_template(‘sign_up.html‘) else: usern=request.form.get(‘username‘) nickn= request.form.get(‘nickname‘) passw = request.form.get(‘password‘) user=User.query.filter(User.username==usern).first() if user: return ‘该用户名已存在‘ else: user1=User(username=usern,nickname=nickn,password=passw) db.session.add(user1) db.session.commit() return redirect(url_for(‘sign_in‘))
主py文件中:
- @app.route设置methods
- GET
- POST
- 读取表单数据
- 查询数据库
- 用户名密码对:
- 记住用户名
- 跳转到首页
- 用户名密码不对:
- 提示相应错误。
- 用户名密码对:
session:
- 从`flask`中导入`session`
- 设置`SECRET_KEY`
- 操作字典一样操作`session`:增加用户名`session[‘username‘]=`username
@app.route(‘/sign_in/‘,methods=[‘GET‘,‘POST‘]) def sign_in(): if request.method == ‘GET‘: return render_template(‘sign_in.html‘) else: username = request.form.get(‘username‘) password = request.form.get(‘password‘) user = User.query.filter(User.username == username).first() if user: if user.check_password(password): session[‘user‘]=username session[‘userid‘]=user.id session.permanent = True return redirect(url_for(‘base‘)) else: return ‘密码错误‘ else: return ‘用户名不存在‘
- 用上下文处理器app_context_processor定义函数
- 获取session中保存的值
- 返回字典
- 在父模板中更新导航,插入登录状态判断代码。
- 注意用{% ... %}表示指令。
- {{ }}表示变量
- 完成注销功能。
- 清除session
- 跳转
@app.route(‘/logout/‘) def logout(): session.clear() return redirect(url_for(‘base‘))
- 编写要求登录的装饰器
from functools import wraps
def loginFirst(func): #参数是函数
@wraps(func)
def wrapper(*args, ** kwargs): #定义个函数将其返回
#要求登录
return func(*args, ** kwargs)
return wrapper #返回一个函数
- 应用装饰器,要求在发布前进行登录,登录后可发布。
@app.route(‘/question/‘,methods=[‘GET‘,‘POST‘])
@loginFirst
def question():
- 建立发布内容的对象关系映射。
class Question(db.Model):
- 完成发布函数。
保存到数据库。
重定向到首页。
def loginFirst(func): @wraps(func) def wrapper(*args,**kwargs): if session.get(‘user‘): return func(*args,**kwargs) else: return redirect(url_for(‘sign_in‘)) return wrapper
<div class="box"> <h2>发布问答</h2> <form action="{{ url_for(‘questions‘) }}" method="post"> <div class="input_box"> <label for="question">问题</label> <textarea id="question" rows="1" cols="40" name="title"></textarea> </div> <div class="input_box"> <label for="issue">详情</label> <textarea id="issue" rows="5" cols="40" name="detail" ></textarea> </div> <div class="input_box"> <input type="submit" name="commit" value="提交" class="sign-in-button" data-disable-with="提交" onclick="myQuestion()"> </div>
function myQuestion() { var title =document.getElementById("title") var detail = document.getElementById("detail") var creat_time=document.getElementById("creat_time") var author_id =document.getElementById("author_id") var author=document.getElementById("author") var isError = true; if (title.value.length > 100) { oError.innerHTML = "问题请输入100位以内字符" isError = false; } return isError; }
- 将数据库查询结果传递到前端页面 Question.query.all()
- 前端页面循环显示整个列表。
- 问答排序
2.完成问答详情页布局:
- 包含问答的全部信息
- 评论区
- 以往评论列表显示区
{% for foo in questions %} <ul class="list"> <li class="zero"><a href="{{url_for(‘usercenter‘,user_id=foo.author_id,tag=1) }}">{{ foo.author.username }}</a></li><br> <li class="one" ><a href="{{ url_for("detail",question_id=foo.id) }}">标题:{{ foo.title }}</a></li> <li class="one" >详情:{{ foo.detail }}</li> <br> <li>发布时间:{{ foo.creat_time }}</li> <br> </ul> {% endfor %}
@app.route(‘/question/‘,methods=[‘GET‘,‘POST‘]) @loginFirst def questions(): if request.method==‘GET‘: return render_template(‘questions.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) user = User.query.filter(User.username == session.get(‘user‘)).first() question.author = user db.session.add(question)#保存到数据库 db.session.commit()#提交 return redirect(url_for(‘base‘))
{{ url_for(‘detail‘,question_id = foo.id) }}
3.在详情页将数据的显示在恰当的位置。
4.建立评论的对象关系映射:
class Comment(db.Model):
__tablename__=‘comment‘
@app.route(‘/detail/<question_id>‘) def detail(question_id): quest=Question.query.filter(Question.id==question_id).first() return render_template(‘detail.html‘,ques=quest)
<ul class="list"> <div class="page-header"> <h3>{{ ques.title }}<br></h3> <small>{{ ques.author.username }}</small> </div> <p class="answer" style="text-indent: 18px">{{ ques.detail }}</p> <hr> <form action="{{ url_for(‘comment‘) }}" method="post"> <span class="badge">{{ ques.creat_time }}</span> <div> <textarea name="new_comment" class="form-control" rows="3" id="new-comment" placeholder="我也说一句..."></textarea> <input name="question_id" type="hidden" value="{{ ques.id }}" > </div> <button type="submit" class="btn btn-default">发送</button> <h4>评论:({{ ques.comments|length }})</h4><br> <ul> {% for ques in ques.comments %} <li> <a href="{{ url_for(‘usercenter‘,user_id=ques.author_id,tag=3) }}">{{ ques.author.username }}</a> <span class="badge">{{ ques.creat_time }}</span><br> <p>评论:{{ ques.detail }}</p> </li> {% endfor %} </ul>
1.定义评论的视图函数
@app.route(‘/comment/‘,methods=[‘POST‘])
def comment():
读取前端页面数据,保存到数据库中
@app.route(‘/comment/‘, methods=[‘POST‘]) def comment(): comment_detail = request.form.get(‘new_comment‘) quest_id = request.form.get(‘question_id‘) author_id = User.query.filter(User.username == session.get(‘user‘)).first().id comment = Comment(detail=comment_detail, author_id=author_id, question_id=quest_id, ) db.session.add(comment) db.session.commit() return redirect(url_for(‘detail‘, question_id=quest_id))
2.用<input type="hidden" 方法获取前端的"question_id"
<input name="question_id" type="hidden" value="{{ ques.id }}">
3.显示评论次数
<span class="tcomment">评论:({{ ques.comments|length }})</span>
4.要求评论前登录
@app.route(‘/comment/‘, methods=[‘POST‘]) @loginFirst def comment():
5.尝试实现详情页面下的评论列表显示
<ul class="list-group"> {% for com in comment %} <li ><a href="#">{{ com.author.username }}</a> <br> <span >{{ com.create_time }}</span> <p class="abstract">{{ com.detail }}</p> </li> {% endfor %} </ul>
1.显示所有评论
{% for foo in ques.comments %}
<ul class="list-group"> {% for foo in question %} <li class="list-group-item"> <span class="glyphicon-leaf" aria-hidden="true"></span> <img id="qu" src="{{ url_for(‘static‘,filename=‘images/title.png‘)}}"> <a href = "#">{{ foo.author.username }}{{ foo.title }}</a> <span class="badge">{{ foo.create_time }}</span> </li> {% endfor %} </ul>
2.所有评论排序
uquestion = db.relationship(‘Question‘, backref=db.backref(‘comments‘, order_by=creat_time.desc))
‘comments‘: Comment.query.order_by(‘create_time‘).all()
3.显示评论条数
{{ ques.comments|length }}
<span class="tcomment">评论:({{ ques.comments|length }})</span>
4.完成个人中心
1.个人中心的页面布局(html文件及相应的样式文件)
2.定义视图函数def usercenter(user_id):
3.向前端页面传递参数
4.页面显示相应数据
发布的全部问答
发布的全部评论
个人信息
{% extends ‘index.html‘ %} {% block title %}usercenter {% endblock%} {% block main%} <div class="page-header"> <h3><span class="glyphicon glyphicon-user" aria-hidden="true"></span> {{username}} <br> <small>全部问答><span class="badge"></span> </small></h3> <ul class="list-group" style=""> {% for foo in question %} <li class="list-group-item"> <span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span> <a href="#">{{foo.author.username }}</a> <span class="badge">{{foo.creat_time}}</span> <p style="">{{foo.detail}}</p> </li> {% endfor %} </ul> </div> <div class="page-header"> <h3><span class="glyphicon glyphicon-user" aria-hidden="true"></span> {{user}} <br> <small>个人信息><span class="badge"></span> </small></h3> <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="#">{{foo.author.username }}</a> <span class="badge">{{foo.creat_time}}</span> <p style="">{{foo.detail}}</p> </li> {% endfor %} </ul> </div> <div class="page-header"> <h3><span class="glyphicon glyphicon-user" aria-hidden="true"></span> {{user}} <br> <small>个人信息><span class="badge"></span> </small></h3> <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> {% endblock %}
5.各个页面链接到个人中心
<a href = "{{ url_for (‘userCenter‘,user_id=each.author.id) }}">{{ foo.author.username }}{{ foo.title }}</a>
1.新页面userbase.html,用<ul ><li role="presentation"> 实现标签页导航。
<ul class="nav nav-tabs">
<li role="presentation"><a href="#">Home</a></li>
<li role="presentation"><a href="#">Profile</a></li>
<li role="presentation"><a href="#">Messages</a></li>
</ul>
2.让userbase.html继承base.html。
重写title,head,main块.
将上述<ul>的样式放在head块,<ul>放在main块中.
定义新的块user。
{% extends "index.html" %} {% block usertitle %}个人中心{% endblock %} {% block userhead %} <style> .nav_ul li{ list-style: none; float: left; margin: 10px; margin-top: 5cm; } </style> {% endblock %} {% block mywebbody %} <ul class="nav_ul"> <li role="presentation"><a href="#">questions</a> </li> <li role="presentation"><a href="#">comments</a> </li> <li role="presentation"><a href="#">information</a> </li> </ul> {% block usercenterbody %}{% endblock %} {% endblock %} </html>
3.让上次作业完成的个人中心页面,继承userbase.html,原个人中心就自动有了标签页导航。
4.制作个人中心的三个子页面,重写userbase.html中定义的user块,分别用于显示问答、评论、个人信息。
{% extends ‘userbase.html‘ %} {% block user %} <div class="page-header"> <h3><span class="glyphicon glyphicon-user" aria-hidden="true"></span> {{username}} <br> <small>全部问答><span class="badge"></span> </small></h3> <ul class="list-group" style=""> {% for foo in question %} <li class="list-group-item"> <span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span> <a href="#">{{foo.author.username }}</a> <span class="badge">{{foo.creat_time}}</span> <p style="">{{foo.detail}}</p> </li> {% endfor %} </ul> </div> {% endblock %}
{% extends ‘userbase.html‘ %} {% block user %} <div class="page-header"> <h3><span class="glyphicon glyphicon-user" aria-hidden="true"></span>{{ user }}<br><small>全部评论<span class="badge>"></span> </small> </h3> <ul class="list-group"style="margin:10px"> {% for foo in comments %} <li class="list-group-item"> <span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span> <a href="#">{{ foo.author.username }}</a> <span class="badge">{{ foo.creat_time }}</span> <p style="align-content: center">{{ foo.detail }}</p> </li> {% endfor %} </ul> </div> {% endblock %}
{% extends ‘userbase.html‘ %} {% block user %} <div class="page-header"> <h3><span class="glyphicon glyphicon-user" aria-hidden="true"></span>{{ user }}<br><small>个人信息<span class="badge>"></span> </small> </h3> <ul class="list-group"style="margin:10px"> <li class="list-group-item">用户:{{ username }}</li> <li class="list-group-item">编号:</li> <li class="list-group-item">昵称:</li> </ul> </div> {% endblock %}
1.个人中心—视图函数带标签页面参数tag
@app.route(‘/usercenter/<user_id>/<tag>‘)
def usercenter(user_id, tag):
if tag == ‘1‘:
return render_template(‘usercenter1.html‘, **context)
@app.route(‘/usercenter/<user_id>/<tag>‘) @loginFirst def usercenter(user_id,tag): user=User.query.filter(User.id==user_id).first() context={ ‘user‘:user, ‘question‘:user.question, ‘comments‘:user.comments } if tag == ‘1‘: return render_template(‘user_com.html‘, **context) elif tag == ‘2‘: return render_template(‘user_ques.html‘, **context) else: return render_template(‘user_info.html‘, **context)
2.个人中心—导航标签链接增加tag参数
<li role=“presentation”><a href=“{{ url_for(‘usercenter’,user_id = user.id,tag = ‘1’) }}">全部问答</a></li>
{% extends "index.html" %} {% block title %}usercenter {% endblock %} {% block head %} <style> .nav_ul li{ list-style: none; float: left; margin: 25px; } </style> {% endblock %} {% block main %} <h3><span class="glyphicon glyphicon-user" aria-hidden="true"></span>{{ user.username }}</h3> <ul class="nav_ul"> <li role="presentation"><a href="{{ url_for(‘usercenter‘,user_id=user.id,tag=1) }}">全部问答</a></li> <li role="presentation"><a href="{{ url_for(‘usercenter‘,user_id=user.id,tag=2) }}">全部评论</a></li> <li role="presentation"><a href="{{ url_for(‘usercenter‘,user_id=user.id,tag=3) }}">个人信息</a></li> </ul> {% block user %}{% endblock %} {% endblock %}
3.个人中心—有链接到个人中心页面的url增加tag参数
<a href="{{ url_for(‘usercenter‘,user_id = session.get(‘userid‘), tag=1) }}">{{ session.get(‘user‘) }}</a>
base.html:
<a href="{{ url_for(‘usercenter‘,user_id=foo.author_id,tag=3) }}">{{ foo.author.username }}</a></li><br>
index.html:
<a href="{{ url_for(‘usercenter‘,user_id=session.get(‘userid‘),tag=3) }}" style="margin-right: -10px;color:deepskyblue">{{ session.get(‘user‘) }}</a>
detail.html:
<a href="{{ url_for(‘usercenter‘,user_id=ques.author_id,tag=3) }}">{{ ques.author.username }}</a>
1.更新User对象,设置对内的_password
class User(db.Model):
__tablename__ = ‘user‘
_password = db.Column(db.String(200), nullable=False) #内部使用
class User(db.Model): __tablename__ = ‘User‘ _password = db.Column(db.String(200),nullable=False)
2.编写对外的password
from werkzeug.security import generate_password_hash, check_password_hash
@property
def password(self): #外部使用,取值
return self._password
@password.setter
def password(self, row_password):#外部使用,赋值
self._password = generate_password_hash(row_password)
@property def password(self): #外部使用,取值 return self._password @password.setter def password(self, row_password):#外部使用,赋值 self._password = generate_password_hash(row_password)
3.密码验证的方法:
def check_password(self, row_password): #密码验证
result = check_password_hash(self._password,row_password)
return result
def check_password(self, row_password): #密码验证 result = check_password_hash(self._password,row_password) return result
4.登录验证:
password1 = request.form.get(‘password‘)
user = User.query.filter(User.username == username).first()
if user:
if user.check_password(password1):
def sign_in(): if request.method == ‘GET‘: return render_template(‘sign_in.html‘) else: username = request.form.get(‘username‘) password1 = request.form.get(‘password‘) user = User.query.filter(User.username == username).first() if user: if user.check_password(password1): session[‘user‘]=username session[‘userid‘]=user.id session.permanent = True return redirect(url_for(‘base‘)) else: return ‘密码错误‘ else: return ‘用户名不存在‘
1.准备视图函数search()
@app.route(‘/search/‘) def search():
2.修改base.html 中搜索输入框所在的
a.<form action="{{ url_for(‘search‘) }}" method="get">
b. <input name="q" type="text" placeholder="请输入关键字">
<form action="{{ url_for(‘search‘) }}" method="get"> <li><input name =‘q‘ type="text" placeholder="请输入您要搜索的关键字..."> <button type="submit"></button></li> </form>
3.完成视图函数search()
a.获取搜索关键字
q = request.args.get(‘q’)
b.条件查询
qu = Question.query.filter(Question.title.contains(q)).order_by(‘-creat_time’)
c.加载查询结果:
return render_template(‘index.html‘, question=qu)
@app.route(‘/search/‘) def search(): qu=request.args.get(‘q‘) ques = Question.query.filter(Question.title.contains(qu)).order_by(‘-creat_time‘) return render_template("base.html",questions=ques)
4.组合条件查询
from sqlalchemy import or_, and_
ques = Question.query.filter(or_(Question.title.contains(qu), Question.detail.contains(qu))).order_by(‘-creat_time‘)