期末作品检查
1.个人学期总结 :经过一个学期的学习我对Python有了一定程度的认识,这些认识离不开杜云梅老师的手把手教学在此谢谢老师一个学期对我们的付出。前期接触Python是通过老师上课解析什么是Python,信息管理系统这门课主要学什么然后慢慢融入代码教学。一开始从基础开始我们学习了Python的基础语法,输入、输出、交互、数字计算的方法、字符串基本操作、凯撒密码、自制九九乘法表、中英文词频统计等,还学习了import turtle库,并利用这个库绘制出多种多样的图形使我们更有兴趣继续学习下去。然后我们就学习了中期学习了web基础,用html元素制作web界面。练习使用下拉列表选择框、无序列表、有序列表、定义列表。开始制作自己的导航条。练习样式表:行内样式表、内嵌样式表、外部样式表。后期我们开始了Flask项目,加载静态文件,父模板的继承和扩展,连接mysql数据库,创建用户模型,建立mysql和app的连接。通过用户模型,对数据库进行增删改查操作。完成注册功能,将界面的数据存到数据库,redirect重定向登录页。完成登录功能,用session记住用户名,增加用户名。登录之后更新导航。在父模板中更新导航,插入登录状态判断代码。完成注销功能,清除session。发布功能的实现,制作首页的显示列表,首页列表显示全部问答,完成问答详情页布局,从首页问答标题到问答详情页,完成评论功能,完成评论列表显示及排序,个人中心显示,个人中心标签页导航,完成个人中心—导航标签,实现搜索功能(包括高级搜索等),最重要的是实现密码加密功能。还做了模型分离与数据迁移,让数据管理更加高效简洁还使用Flask中render_template,用不同的路径,返回首页、登录员、注册页。用视图函数反转得到URL,url_for(‘login’),完成导航里的链接。加载静态文件,进行父模板的继承和扩展,实现自己代码的需求。在学习Python+Flask+MysqL的web建设时,需要安装数据库(mysql)、开发工具(pycharm)和开发需要用到的第三方库。
2.总结Python+Flask+MysqL的web建设技术过程:
导航栏和首页
注册页面

登录页面

发布问答页面
问答详情页

个人中心



主要代码:
from flask import Flask, render_template, redirect, url_for,request,session from flask_sqlalchemy import SQLAlchemy from datetime import datetime from functools import wraps from sqlalchemy import or_,and_ import config from werkzeug.security import generate_password_hash,check_password_hash app = Flask(__name__) app.config.from_object(config) db = SQLAlchemy(app) #创建用户模型 class User(db.Model): __table__name = '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) #内部使用 @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_passwprd): result = check_password_hash(self._password, row_passwprd) 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) create_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')) create_time = db.Column(db.DateTime, default=datetime.now) detail = db.Column(db.Text, nullable=False) question = db.relationship('Question',backref = db.backref('comments', order_by=create_time.desc)) author = db.relationship('User',backref = db.backref('comments')) db.create_all() ''' 增加 user = User(username='qingting',password='123') db.session.add(user) db.session.commit() 查询 user = User.query.filter(User.username == 'qingting').first() print(user.username,user.password) 修改 user=User.query.filter(User.username == 'qingting').first() user.password=1234567 db.session.commit() 删除 user=User.query.filter(User.username == 'qingting').first() db.session.delete(user) db.session.commit() '''
导航栏首页的html代码(用于其他网页的继承):
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %}{% endblock %}问答平台</title> {# <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='css/basic.css') }}" base href="" target="_blank">#} <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> {% if username %} <a href="{{ url_for('usercenter',user_id = session.get('userid'),tag=1) }}">{{ session.get('user') }}</a> {% else %} <div class="container"> <div class="row clearfix"> <div class="col-md-12 column"> <nav class="navbar navbar-default" role="navigation"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"> <span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button> <a class="navbar-brand" href="#">carrie</a> </div> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li> <a href="{{ url_for('index') }}">首页</a> </li> <li> <a href="{{ url_for('question') }}">发布问答</a> </li> <li> <a href="{{ url_for('login') }}">登录</a> </li> <li> <a href="{{ url_for('regist') }}">注册</a> </li> <li> <a href="{{ url_for('logout') }}">注销</a> </li> </ul> <form action="{{ url_for('search') }}" method="get" class="navbar-form navbar-left" role="search"> <div class="form-group"> <input name="q" type="text" class="form-control" placeholder="请输入关键字"/> </div><button type="submit" class="btn btn-default">搜索</button> {% endif %} </form> <script> function mySwitch() { var oBody = document.getElementById("myBody"); var oOnOff = document.getElementById("myOnOff"); if(oOnOff.src.match("bulbon")){ oOnOff.src="http://www.runoob.com/images/pic_bulboff.gif"; oBody.style.background="black"; oBody.style.color="darksalmon"; }else { oOnOff.src="http://www.runoob.com/images/pic_bulboff.gif"; oBody.style.background="darksalmon"; oBody.style.color="black"; } } </script> <img id="myOnOff" onclick="mySwitch()" src="http://www.runoob.com/images/pic_bulbon.gif" width="30px";> </div> </nav> </div> </div> </div> {% block main %} {% endblock %} </head> <body id="myBody"> </body> </html>
注册页面的代码:
{% extends'base.html' %}
{% block title %}注册{% endblock %}
{% block head %}
<script src="{{ url_for('static',filename='js/regist.js') }}"></script>
{% endblock %}
{% block main %}
<style>
.input_box {
width: 325px;
height: 50px;
padding-left: 7px;
padding-right: 7px;
background: none;
line-height: 30px;
font-size: 16px;
{# color: bisque;#}
vertical-align: middle;
}
.box{
align-content: center;
background-color: cadetblue;
height:450px;width:400px;float:left;
text-align: center;
vertical-align: middle;
position: absolute;
top: 50%;
left: 50%;
margin: -150px 0 0 -150px;
border: 1px solid #ccc;
border-radius: 20px;
}
.jj{
width: 78px;
margin: 10px 0;
padding: 8px 18px;
font-size: 20px;
border: none;
border-radius: 20px;
color: #fff!important;
background-color: darkslateblue;
cursor: pointer;
outline: none;
}
body {
background-color: #ffffff;
}
.dd{
font-size:28px;
color: #fff;
}
</style>
<div class="box">
<h2 class="dd">注册</h2>
<form action="{{ url_for('regist') }}" method="post">
<div class="input_box">
用户名:<input id="uname" type="text" placeholder="请输入用户名" name="username">
</div>
<div class="input_box">
手机号:<input id="uphonenumeber" type="text" placeholder="请输入手机号" name="userphone">
</div>
<div class="input_box">
邮 箱: <input id="uemaill" type="text" placeholder="请输入邮箱" name="useremail">
</div>
<div class="input_box">
密 码: <input id="upassworld" type="password" placeholder="请输入密码" name="password">
</div>
<div class="input_box">
确认密码:<input id="upassworld1" type="password" placeholder="请再次输入密码">
</div>
<div id="error_box"><br></div>
<div>
<button class="jj" onclick="fnRegist()">确认注册</button>
</div>
</form>
</div>
{% endblock %}
注册的js文件:
function fnRegist() { var oUame = document.getElementById("uname") var oError = document.getElementById("error_box") var oPass = document.getElementById("upassworld").value; var oPass1 = document.getElementById("upassworld1").value; var isoError = true; oError.innerHTML = "<br>" //uname if (oUame.value.length<6 || oUame.value.length>20) { oError.innerHTML = "用户名为6-10位"; isError = false; return isoError; }else if((oUame.value.charCodeAt(0)>=48) && (oUame.value.charCodeAt(0)<=57) ){ oError.innerHTML="用户名首字母不能是数字"; isError = false; return isoError; }else for(var i=0; i<oUame.value.length;i++){ if((oUame.value.charCodeAt(i)<48||(oUame.value.charCodeAt(i)>57)&&(oUame.value.charCodeAt(i)<97 || (oUame.value.charCodeAt(i)>122)))){ oError.innerHTML="只能是数字或字母"; isError = false; return isoError; } } //upassword if(opass.value.length<6 || opass.value.length>20){ oError.innerHTML = "密码为6-20位"; isError = false; return isoError; } if (oPass!=oPass1){ document.getElementById("error_box").innerHTML = "两次密码不一致" isError = false; return isoError; } return isoError; window.alert("注册成功!") }
注册页面用到的函数:
@app.route('/regist/' , methods=['GET','POST']) def regist(): if request.method == 'GET': return render_template('regist.html') else: username = request.form.get('username')# 获取form中的数据 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) db.session.add(user)#数据库操作 db.session.commit() return redirect(url_for('login'))#重新到登录页
登录页面代码:
{% extends'base.html' %}
{% block title %}登录{% endblock %}
{% block head %}
<script src="{{ url_for('static',filename='js/login.js') }}"></script>
{% endblock %}
{% block main %}
<style>
.input_box {
width: 325px;
height: 50px;
padding-left: 7px;
padding-right: 7px;
background: none;
line-height: 30px;
font-size: 16px;
{# color: bisque;#}
vertical-align: middle;
}
.box{
align-content: center;
background-color: cadetblue;
height:260px;width:340px;float:left;
text-align: center;
vertical-align: middle;
position: absolute;
top: 50%;
left: 50%;
margin: -150px 0 0 -150px;
border: 1px solid #ccc;
border-radius: 20px;
}
.jj{
width: 78px;
margin: 10px 0;
padding: 8px 18px;
font-size: 20px;
border: none;
border-radius: 20px;
color: #fff!important;
background-color: darkslateblue;
cursor: pointer;
outline: none;
}
body {
background-color: #ffffff;
}
.dd{
font-size:28px;
color: #fff;
}
</style>
<div class="box">
<h2 class="dd">登录</h2>
<form action="{{url_for('login')}}" method="post">
<div class="input_box">
用户名:<input id="username" type="text" placeholder="请输入用户名" name="username">
</div>
<div class="input_box">
密 码: <input id="userpassworld" type="password" placeholder="请输入密码" name="password">
</div>
<div id="error_box"><br></div>
<div>
<button class="jj" onclick="fnLogin()">登录</button>
</div>
</form>
</div>
{% endblock %}
登录的js:
function fnLogin() { var oUame = document.getElementById("uname"); var opass = document.getElementById("upassworld"); var oError = document.getElementById("error_box"); var isError = true; oError.innerHTML = "<br>"; //uname if (oUame.value.length<6 || oUame.value.length>20) { oError.innerHTML = "用户名为6-10位"; isError = false; return isError; }else if((oUame.value.charCodeAt(0)>=48) && (oUame.value.charCodeAt(0)<=57) ){ oError.innerHTML="用户名首字母不能是数字"; isError = false; return isError; }else { for(var i=0; i<oUame.value.length;i++){ if((oUame.value.charCodeAt(i)<48||(oUame.value.charCodeAt(i)>57)&&(oUame.value.charCodeAt(i)<97 || (oUame.value.charCodeAt(i)>122)))){ oError.innerHTML="只能是数字或字母"; isNotError = false; return isError; } } } //upassword if(opass.value.length<6 || opass.value.length>20){ oError.innerHTML = "密码为6-20位"; isError = false; return isError; } return isError; window.alert("登录成功!") }
登录页面用到的函数:
@app.route('/login/' , methods=['GET','POST']) def login(): if request.method == 'GET' : return render_template('login.html') else: username = request.form.get('username')# 获取form中的数据 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.' return redirect(url_for('index')) # 返回首页
详情页面的html:
{% extends'base.html' %}
{% block title %}首页-{% endblock %}
{% block head %}{% endblock %}
{% block main %}
<style>
body{
background-color: #ffffff;
}
.footer{
bottom: 0;
width: 100%;
}
div.img{
border: 1px solid #212ccc;
width:100px;
float: left;
margin: 5px;
}
div.img img{
width: 100%;
height: auto;
}
div,desc{
text-align: center;
padding: 5px;
}
div,img:hover{
border: 1px solid #ffffff;
}
</style>
{# <img src="{{ url_for('static',filename='images/问答.jpg') }}" alt="" width="100">#}
<p>{{ usern }}</p>
{% for foo in questions %}
<ul class="new-list">
<li>
<p>{{ foo.detail }}</p>
<a target="_self" href="{{ url_for('detail',question_id=foo.id) }}">标题:{{ foo.title }}</a><br>
<a href="{{ url_for('usercenter',user_id = foo.author.id,tag = 1) }}">发布者:{{ foo.author.username }}<br></a>
评论:({{ foo.comments|length }})<br>
<span class="post_item_foot">
发布于 {{ foo.create_time }}
</span>
</li>
</ul>
</div>
<hr></div>
{% endfor %}
{% block body %}
<div>
<div class="recommend">
<footer class="footer">
<div class="img">
<img src="{{ url_for('static',filename='images/timg.jpg') }}" alt="" width="100">
<div class="desc"><a href="https://image.baidu.com/search/detail?ct=503316480&z=
0&ipn=d&word=%E5%B8%83%E6%9C%97%E7%86%8A&step_word=&hs=2&pn=6&spn=0&di=
79837637440&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=0&ie=utf-8&oe=utf-8&in=
&cl=2&lm=-1&st=undefined&cs=4254122511%2C4041747366&os=2092177177%2C2042104883&simid=
4288902954%2C717627127&adpicid=0&lpn=0&ln=1971&fr=&fmq=1514876043235_R&fm=&ic=
undefined&s=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=
undefined&ist=&jit=&cg=&bdtype=0&oriquery=&objurl=http%3A%2F%2Fimg4.duitang.com%
2Fuploads%2Fitem%2F201604%2F09%2F20160409191430_AWUck.jpeg&fromurl=ippr_z2C%24qAzd
H3FAzdH3Fooo_z%26e3B17tpwg2_z%26e3Bv54AzdH3Fks52AzdH3F%3Ft1%3Dccblnb0a9&gsm=
0&rpstart=0&rpnum=0">BROWN </a></div>
</div>
</footer>
</div>
</div>
{% endblock %}
{% endblock %}
详情页面的函数:
@app.route('/question/',methods=['GET', 'POST']) # 跳转注册,methods定义它有两种请求方式 @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('/detail/<question_id>') def detail(question_id): quest = Question.query.filter(Question.id == question_id).first() return render_template('detail.html',ques = quest) @app.route('/comment/',methods=['POST']) @loginFirst def comment(): comment = request.form.get('new_comment') ques_id = request.form.get('question_id') auth_id = User.query.filter(User.username == session.get('user')).first().id comm = Comment(author_id=auth_id, question_id=ques_id, detail=comment) db.session.add(comm) db.session.commit() return redirect(url_for('detail' , question_id = ques_id))
用于个人中心继承页面:
{% extends 'user.html' %}
{% block user %}
<style>
{
background-color: antiquewhite;
}
</style>
<script src="{{ url_for('static',filename='js/regist.js') }}"></script>
<div class="page-header">
<h3><span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span>{{ user.username }} <br>
<small>全部问答<span class="badge"></span></small>
</h3>
<ul class="list-group" style="margin: 10px">
{% for foo in user.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.create_time }}</span>
<p>{{ foo.detail }}</p>
</li>
{% endfor %}
</ul>
</div>
<div class="page-header">
<h3><span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span>{{ user.username }} <br>
<small>全部评论<span class="badge"></span></small>
</h3>
<ul class="list-group" style="margin: 10px">
{% for foo in user.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.create_time }}</span>
<p>{{ foo.detail }}</p>
</li>
{% endfor %}
</ul>
</div>
<div class="page-header">
<h3><span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span>{{ user.username }} <br>
<small>个人信息<span class="badge"></span></small>
</h3>
<ul class="list-group" style="margin: 10px">
<li class="list-group-item">用户:{{ user.username }}</li>
<li class="list-group-item">编号:{{ user.id }}</li>
<li class="list-group-item">昵称:{{ user.username }}</li>
<li class="list-group-item">文章:</li>
</ul>
</div>
{% endblock %}
个人中心调用的函数:
@app.route('/user/<user_id>/<tag>') @loginFirst def usercenter(user_id, tag): user = User.query.filter(User.id == user_id).first() context = { 'user':user # 'username':user.username, # 'questions':user.questions, # 'comments':user.comments } if tag == '1': return render_template('usercenter1.html', **context) elif tag == '2': return render_template('usercenter2.html', **context) else : return render_template('usercenter3.html', **context) # return render_template('usercenter.html', **context)
搜索函数:
@app.route('/search/') def search(): qu = request.args.get('q') ques = Question.query.filter( or_ (Question.title.contains(qu), Question.detail.contains(qu), # Question.author_id.contains(qu) ) ).order_by('-create_time') return render_template('index.html',questions = ques)
浙公网安备 33010602011771号