期末作品检
2018-01-03 15:28 055李小锐 阅读(373) 评论(0) 收藏 举报1.总结Python+Flask+MysqL的web建设技术过程。对所学知识的梳理。对初学入门者的简单教程。作为自己以后复习的向导。一种向外展示能力的途径。
个人学期总结
岁月飞逝,时光如梭,很快,一个学期即将过去,在这一学期里,学习了不少关于信息管理的知识,其中很关键的一个内容就是对python语言基础的学习。之前想学python的基本知识的时候,只是在网上查找资料,看看别人博客上的内容,没有整体性的学习和深入的探讨,学的东西很凌乱。而通过本学对python基础知识的学习,发现其实python语言比起其他语言的学习要好入手很多。比如python有很库、获取数据方便、数据运算方便、表达的语句简而易懂、与其他语言交互很方便、信息处理也很方便。就如本学期所画的一个五星红旗,几个循环语句就能将其呈现在屏幕上,这是其他语言做不到的事情。
总的来说,python语言非常简单,阅读一个良好的Python程序就感觉像是在读英语一样,尽管这个对英语的要求非常严格!Python的这种伪代码本质是它最大的优点之一。它使你能够专注于解决问题而不是去搞明白语言本身。在当今的大数据时代,更是需要这种易懂、方便学习的编程语言来处理大数据和得出最优的结论出来。但是python也有缺点,很多时候不能将程序连写成一行,如import sys;for i in sys.path:print i。而perl和awk就无此限制,可以较为方便的在shell下完成简单程序,不需要如Python一样,必须将程序写入一个主.py文件。既是优点也是缺点,python的开源性是的Python语言不能加密。总体来说,python语言还算是比较优秀的,吸引的人才多,项目也多。而本学期就实现了Python+Flask+Mysql的web建设技术的过程,以下是详细解析该技术的实现过程。
具备python基本知识之后,就可以编写web基础
1、先是认识URL,观察常用网址,因为一个网址里面有不同的组成成分,可以利用h标签来编辑不同文本,可以用div来修饰文本样式。用img标签将图片上传至网页,用a标签可以对文字或图片添加链接
<body> <h1>MIS问答平台</h1> <h3>数学</h3> <h6>语文</h6> <p>英语</p> <hr> <P>友情链接</P> <a href="http://www.gzcc.cn/">广州商学院 <br> <img src="http://www.gzcc.cn/2016/images/banner.png" width="258" height="39" alt="gzcc.cn"/></a> </body>


2、对于一个网址,里面有下拉列表选择框,无序列表,有序列表,可以分别通过select标签嵌套option标签、ul标签嵌套li标签、ol标签嵌套li标签的方法来实现该功能,需要注意的是select标签外需要增加一个form表单,from表单可以向后台传递数据
<from> <select> <option>问答</option> <option>提问</option> <option>收藏</option> </select> </from> <ul> <li>教师常用表格</li> <li>学生常用表格</li> <li>教学管理表格</li> <li>教学管理文件</li> <li>参考资料</li> </ul> <ol> <li>教师常用表格</li> <li>学生常用表格</li> <li>教学管理表格</li> <li>教学管理文件</li> <li>参考资料</li> </ol>>

3、<base>可以定义页面链接标签的默认链接地址。<style>定义html文档的样式文件<link>定义一个文档和外部资源之间的关系。而且这三个部分均要放入head里面。可以用url_for加载静态文件<script src="{{ url_for('static',filename='js/login.js') }}"></script>,flask从static文件夹开始寻找,可用于加载css,js,imag文件
<head> <meta charset="UTF-8"> <title>MISS</title> <base href="http://i1.sinaimg.cn/dy/weather/main/index14/007/icons_32_yl/"target="_blank"> <link rel="stylesheet" type="text/css" href="T5.css"> <style type="text/css"> p{ color:darkcyan;font-size: 10px; } .textblue{ color:blue; text-decoration: underline; } </style> </head>
4、继承和扩展:把一些公共的代码放在父模板中,避免每个模板写同样的内容。子模板的继承:每个字模板都要有继承语句 {% extends 'base.html’ %},子模板位置及名称{% block title %}{% endblock %} {% block head %}{% endblock %} {% block main %}{% endblock %}每个部分部分根据自己的需求增加内容。数据库配置信息config.py
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:@127.0.0.1:3306/mis_db?charset=utf8' SQLALCHEMY_TRACK_MODIFICATIONS = False
5、登录与注册功能:
新建Flask项目,使用Flask中render_template,用不同的路径,返回首页、登录员、注册页,用视图函数反转得到URL,{{url_for(‘login’)}},完成导航条里的链接,登录输入框中用户名必须在6-12位,首字母不是数字,整个用户名只能是数字,密码控制在6-12位,注册的时候还要判断输入的两次密码是否一致。登录按钮和注册按钮都得返回onclick="return myLogin(),return myregister()。 从flask中导入session、设置secret_key、操作字典一样操作session增加用户名`session['username']=`username。在主py文件定义注册和登录的视图函数。
.注册js
function myLogin() { var oUname = document.getElementById("uname"); var oError = document.getElementById("error_box"); var opassword = document.getElementById("upass"); var ophone = document.getElementById("phone"); var ocpassword=document.getElementById("cpassword"); oError.innerHTML=="<br>"; if(oUname.value.length<6||oUname.value.length>12){ oError.innerHTML="number of uname6-12"; return false; } else if((oUname.value.charCodeAt(0) >= 48) && (oUname.value.charCodeAt(0)<= 57)){ oError.innerHTML = "first number"; return false; } else for(var i=0; i<oUname.value.length;i++){ if((oUname.value.charCodeAt(i)<48||oUname.value.charCodeAt(i)>57)&&(oUname.value.charCodeAt(i)<97||oUname.value.charCodeAt(i)>122)){ oError.innerHTML="only letter or number"; return false; } } if(ophone.value.length<11||ophone.value.length>11){ oError.innerHTML="number of phone11"; return false; } if(opassword.value.length<6||opassword.value.length>12){ oError.innerHTML="number of password6-12"; return false; } else if (opassword.value!=ocpassword.value){ oError.innerHTML="cpassword error"; return false; } return true; window.alert("注册成功") }
登录js
function myLogin() { var oUname = document.getElementById("uname"); var oError = document.getElementById("error_box"); var opassword = document.getElementById("upass"); var isError=true; oError.innerHTML="<br>"; if(oUname.value.length<6||oUname.value.length>12){ oError.innerHTML="number of uname6-12"; isError=false; return isError; } else if((oUname.value.charCodeAt(0) >= 48) && (oUname.value.charCodeAt(0)<= 57)){ oError.innerHTML = "first number"; isError=false; return isError; } else for(var i=0; i<oUname.value.length;i++){ if((oUname.value.charCodeAt(i)<48||oUname.value.charCodeAt(i)>57)&&(oUname.value.charCodeAt(i)<97||oUname.value.charCodeAt(i)>122)){ oError.innerHTML="only letter or number"; isError=false; return isError; } } if(opassword.value.length<6||opassword.value.length>12){ oError.innerHTML="number of password6-12"; isError=false; return isError; } return isError; window.alert("登录成功!") }
@app.route('/zhuce/', methods=['GET','POST'])
def zhuce():
if request.method == 'GET':
return render_template('zhuce.html')
else:
username = request.form.get('username')
nickname = request.form.get('nickname')
phone = request.form.get('phone')
password = request.form.get('password')
user = User.query.filter(User.username == username).first()
if user:
return 'username existed'
else:
user = User(username=username, password=password, nickname=nickname, phone=phone)
db.session.add(user)
db.session.commit()
return redirect(url_for('login'))
@app.route('/login/', methods=['GET','POST'])
def login():
if request.method == 'GET':
return render_template('login.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('index'))
else:
return u'password error'
else:
return u'username is not existed'


6、新建python与数据库的连接,可以对数据库进行增删改操作
from flask_sqlalchemy import SQLAlchemy
import config
app = Flask(__name__)
app.config.from_object(config)
#增加
user=User(username='mis1234',password='111111')
db.session.add(user)
db.session.commit()
#删除
user = User.query.filter(User.username == 'mis1234').first()
db.session.delete(user)
db.session.commit()
#修改
user = User.query.filter(User.username=='mis114').first()
user.password='499679642'
db.session.commit()
#查询
user = User.query.filter(User.username == 'mis1234').first()
print(user.id,user.password)
7、用上下文处理器app_context_processor定义函数、获取session中保存的值,返回字典。注销功能:消除session,跳转至首页。但是对于发布问题的功能,发布前需要登录,则需要编写要求登录的装饰器。def loginFirst(func): #参数是函数,登录后可以发布,在question装饰器调用@loginFist函即可。发布问题时,需要建立发布内容的对象关系映射 class Question(db.Model):跟注册用户一样的写法。
登录装饰器
def login_re(func):
@wraps(func)
def wrapper(*args, **kwargs):
if session.get('user'):
return func(*args,**kwargs)
else:
return redirect(url_for('login'))
return wrapper
发布视图函数
@app.route('/question/',methods=['GET','POST'])
@loginFirst
def question():
if request.method == 'GET':
return render_template('question.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)
db.session.add(question)
db.session.commit()
return redirect(url_for('index'))
注销
@app.route('/logout/')
def logout():
session.clear()
return redirect(url_for('index'))

发布问答


8、对于首页显示的全部问答,可以通过数据库查询结果传递到前端页面Question.query.all(),前端页面循环显示整个list,问答按发布时间排序。问答的详情布局包括问答的全部信息、评论区、以往评论内容。在首页点击问答可以标题,可以跳转至相应的详情<a href="{{url_for('detail')}}" class="title">{{ foo.title }}</a>。{{ ques.title}}{{ ques.id }}{{ ques.creat_time }} {{ ques.author.username }} {{ ques.detail }}在详情页将数据的像是在恰当的位置。定义评论关系,为后续的发布评论做铺垫
首页获取问答的代码
<p1>Answer Information</p1> <br><br> {% for foo in questions %} <li class="list-group-item" > <span class="glyphicon glyphicon-align-leaf" aria-hidden="true"></span> <img src="{{ url_for('static',filename='images/touxiang.png') }}" alt="lz" width="20px" style="border-radius: 80px;">{{ foo.author.username }}<br> <a href="{{url_for('detail',question_id=foo.id)}}">{{ foo.title }}</a> <span class="badge" style="margin-left: 60%">{{ foo.creat_time }}</span> <p style="text-indent: 18px">{{ foo.detail }}</p> <img src="{{ url_for('static',filename='images/dianzhan.png') }}" alt="lz" width="20px" style="border-radius: 20%;">12 <img src="{{ url_for('static',filename='images/yuedu.png') }}" alt="lz" width="20px"style="margin-left: 2%;border-radius: 20%;">86 <span style="margin-left:4%">评论:({{ foo.comments|length }})</span> </li> {% endfor %}
问答详情页
<p1>Comment Information</p1> <li class="list-group-item"> <h3>{{ ques.title}}<br>{{ ques.detail }}<br> <img src="{{ url_for('static',filename='images/touxiang.png') }}" alt="lz" width="20px" style="border-radius: 80px;"><small>{{ ques.author.username }}<span class="badge">{{ ques.creat_time }}</span> </small></h3> <hr> <form action="{{url_for('comment')}}" method="post"> <div class="form-group"> <textarea name="new_comment" class="form-control" rows="3" id="new_comment" placeholder="评论内容" name="detail"></textarea> <input name="question_id" type="hidden" value="{{ ques.id }}"/> </div> <button type="submit" class="btn btn-default">发送</button> </form> <hr> 评论:({{ ques.comments|length }}) {% for foo in ques.comments %} <li class="list-group-item"> <span class="glyphicon glyphicon-align-leaf" aria-hidden="true"></span> <img src="{{ url_for('static',filename='images/touxiang.png') }}" alt="lz" width="20px" style="border-radius: 80px;"> <a href="{{ url_for('usercenter',user_id=foo.author.id,tag=1) }}">{{ foo.author.username }}</a> <span class="badge">{{ foo.creat_time }}</span> <p>{{ foo.detail }}</p> </li></li> {% endfor %} </ul>
定义详情页视图函数
@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)
定义评论的映射关系
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'))
detail=db.Column(db.DateTime,default=datetime.now)
question=db.relationship('Question',backref=db.backref('comments',order_by=creat_time.desc))
author=db.relationship('User',backref=db.backref('comments'))
9、定义评论的视图函数@app.route('/comment/',methods=['POST'],读取前端页面数据,并存入数据库中。此外,用<input type="hidden" 方法获取前端的"question_id" ,可以用于显示评论次数。
详情页下显示评论的代码。
{% for foo in ques.comments %} <li class="list-group-item"> <span class="glyphicon glyphicon-align-leaf" aria-hidden="true"></span> <img src="{{ url_for('static',filename='images/touxiang.png') }}" alt="lz" width="20px" style="border-radius: 80px;"> <a href="{{ url_for('usercenter',user_id=foo.author.id,tag=1) }}">{{ foo.author.username }}</a> <span class="badge">{{ foo.creat_time }}</span> <p>{{ foo.detail }}</p>
10、完成个人中心的页面布局、定义视图函数def usercenter(user_id):,向前段页面传递参数、页面显示相应数据,其中包括发布问答的全部问答、发布的全部评论、发布者的个人信息。新页面userbase.html,用<ul ><li role="presentation"> 实现标签页导航,让userbase.html继承base.html,重写title,head,main块。原个人中心就自动有了标签页导航。制作个人中心的三个子页面,重写userbase.html中定义的user块,分别用于显示问答、评论、个人信息。标签页导航到达不同的个人中心子页面。个人中心视图函数带标签页面参数tag,个人中心导航标签链接增加tag参数,个人中心有链接到个人中心的url增加tag参数。
个人中心视图函数
@app.route('/usercenter/<user_id>/<tag>')#个人中心 @login_re def usercenter(user_id,tag): user=User.query.filter(User.id==user_id).first() context={ 'user':user } if tag=='1': return render_template('user1.html',**context) elif tag=='2': return render_template('user2.html', **context) else: return render_template('user3.html', **context)
usercenter.html
{% extends 'userbase.html' %}
{% block head %}
<link rel="stylesheet" href="{{ url_for('static',filename='css/userbase.css') }}" >
<script src="{{ url_for('static',filename='js/usercenter.js') }}" type="text/javascript"></script>
{% endblock %}
<ul class="list-group " style="width: 50%; margin:0 auto">
{% block user %}
<br>
<h3>{{ username }}<br>全部问答</h3>
{% for foo in user.question %}
<li class="list-group-item">
<span class="glyphicon glyphicon-align-leaf" aria-hidden="true"></span>
<a href="#">{{ foo.author.username }}</a>
<br>
<span class="badge" style="margin-left: 60%">{{ foo.creat_time }}</span>
<p style="text-indent: 18px">{{ foo.detail }}</p>
</li>
{% endfor %}
<hr>
<h3>全部评论</h3>
{% for foo in user.comments %}
<li class="list-group-item">
<span class="glyphicon glyphicon-align-leaf" aria-hidden="true"></span>
<a href="#">{{ foo.author.username }}</a>
<span class="badge">{{ foo.creat_time }}</span>
<p>{{ foo.detail }}</p>
</li>
{% endfor %}
<hr>
<h3>个人信息</h3>
<span class="glyphicon glyphicon-align-leaf" aria-hidden="true"></span>
<li class="list-group-item">用户:{{user.username}}<br>
编号:{{user.id}}<br>
昵称:{{user.nickname}}<br>
文章篇数:{{ user.question|length }}<br>
评论数:{{ user.comments|length }}
</li>
</ul>
userbase.html
{% extends 'base.html' %} {% block title %}Infobase{% endblock %} {% block head %} <link rel="stylesheet" href="{{ url_for('static',filename='css/userbase.css') }}" > <script src="{{ url_for('static',filename='js/userbase.js') }}" type="text/javascript"></script> {% endblock %} {% block main %} <ul class="list-group " style="width: 50%; margin:3rem auto"> <ul class="nav_ul "> <lia role="presentation"><a href="{{ url_for('usercenter',user_id=user.id,tag='1') }}">Questions</a> </lia> <lia role="presentation"><a href="{{ url_for('usercenter',user_id=user.id,tag='2') }}">Comments</a> </lia> <lia role="presentation"><a href="{{ url_for('usercenter',user_id=user.id,tag='3') }}">Info</a> </lia> </ul> {% block user %}{% endblock %} </ul> {% endblock %}
user1.html,user2.html,user3.html原理相同,只需把main里面的传递内容修改一下即可,下面是user1.html的代码
{% extends 'userbase.html' %} <link rel="stylesheet" href="{{ url_for('static',filename='css/usercenter.css') }}" > <script src="{{ url_for('static',filename='js/usercenter.js') }}" type="text/javascript"></script> {% block user %} <br><br> <h3>{{ username }}全部问答</h3> {% for foo in user.question %} <li class="list-group-item"> <span class="glyphicon glyphicon-align-leaf" aria-hidden="true"></span> <img src="{{ url_for('static',filename='images/touxiang.png') }}" alt="lz" width="20px" style="border-radius: 80px;"> <a href="#">{{ foo.author.username }}</a> <p style="text-indent: 18px">{{ foo.title }}</p> <p style="text-indent: 18px">{{ foo.detail }}</p> <img src="{{ url_for('static',filename='images/dianzhan.png') }}" alt="lz" width="20px" style="border-radius: 20%;">23 <img src="{{ url_for('static',filename='images/yuedu.png') }}" alt="lz" width="20px"style="margin-left: 2%;border-radius: 20%;">66 <span class="badge" style="margin-left: 60%">{{ foo.creat_time }}</span> </li> {% endfor %} {% endblock %}



11、准备视图函数search(),增加base.html中搜索输入框的action="{{ url_for('search') }} 按钮增加name=“q”,视图函数需要获取搜索关键字、增加条件查询、加载查询结果。return render_template('index.html', question=qu)。
search视图函数
@app.route('/search/')
def search():
qu=request.args.get('q')
ques=Question.query.filter(
or_(
Question.title.contains(qu),
Question.detail.contains(qu)
)
).order_by('-creat_time')
return render_template('index.html',questions=ques)

12、密码保护功能实现步骤:更新user对象,设置对内的_password,编写对外的password,密码验证、登录验证
内置对内的_password:
_password = db.Column(db.String(200), nullable=False) #内部使用
编写对外的passoword:
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)
密码验证:
def check_password(self, row_password): #密码验证
result = check_password_hash(self._password,row_password)
return result
登录验证:
password1 = request.form.get('password')
user = User.query.filter(User.username == username).first()
if user:
if user.check_password(password1):

浙公网安备 33010602011771号