-
个人学期总结
在这个学期里,在老师带领下,我们学习了管理信息系统这门课程。由一开始懵懵懂懂的概念知识到后面基本熟悉的上机操作,这都离不开老师对我们一步步的指导。在这个课程中我发现,跟随老师的步伐,做出一个界面并不代表什么,而是需要课后多加熟悉,上手操作,才能算是掌握这门课程的核心。
在一开始接触Python,我们首先是做了一系列的基础练习,例如:简单输入输出交互、用户输入两个数字,计算并输出两个数字之和、输入半径,计算圆的面积等等一系列的简单代码训练,然后了解turtle库(海龟库)并在这个环境下进行基础训练,画出同切圆、同心圆、五角星,在慢慢由浅及深画黄色实心五角星、最后画国旗等等。再慢慢地由简单的多句代码实现绘画到利用条件、循环、函数定义减少代码数量实现绘画,其实就是利用简单的例子让我们熟悉Python环境,并从中学习到一些Python语言。接着就开始进行字符串的基本操作、凯撒密码、自制九九乘法表等等,再让我们进行中英文词频统计等组合数据类型练习。最后利用datetime处理日期和时间,将字符串转化成imestamp与timedelta,同时了解管理信息系统概念与基础,理解数据存储的方式如字典、列表、元祖、集合,了解到与Web相关的一些基础知识。让我们再简单的例子中熟悉并对Python产生兴趣,也在一些简单的例子里为之后的网页制作打下良好的基础。
在中期,我们开始Web的各种练习,首先进行Web的基础训练,练习使用标签制作简单的页面。然后开始用div,form制作登录页面,练习使用下拉列表选择框,无序列表,有序列表,定义列表。也开始制作自己喜欢的导航条,其中包含HTML头部元素:<base> 定义了页面链接标签的默认链接地址、<style> 定义了HTML文档的样式文件、<link> 定义了一个文档和外部资源之间的关系;各种样式表;还有三类样式表。还有开始学习初步运用css做图片导航块,使用JS定义函数进行登录注册验证,完成登录与注册页面的前端HTML设计。到后面就开始了Flask框架制作网页的学习。
在开始Flask项目开始后,我们学习了夜间模式的开启与关闭、父模板的制作,制作网站网页共有元素的父模板html,包括顶部导航,中间区块划分,底部导航等形成完整的一个html+css+js,把一些公共的代码放在父模板中,避免每个模板写同样的内容;然后学习了用url_for加载静态文件,用 render_template,用于创建一个Flask对象以及页面的跳转,进行父模板的继承和扩展,实现自己代码的需求。然后就开始安装与配置python3.6+flask+mysql数据库,建立mysql和app的连接,引入flask_sqlalchemy库进行数据库的关联映射,创建用户模型,对数据库进行增删改查操作。完成注册功能,将页面的数据存到数据库,redirect重定向登录页;完成登录功能,用session记住用户名,像操作字典一样操作‘session’:增加用户名‘session[‘username’]’=username。登录之后更新导航,用上下文处理器app_context_processor定义函数,获取session中保存的值,返回字典,在父模板中更新导航,插入登录状态判断代码。让登录后的导航显示登录用户的名字。接着完成注销功能,清除session。让注销后的导航栏上返回原来模样。后面完善发布功能,添加装饰器,需要用户发布前进行登录操作,登录后方可发布。建立发布内容的对象关系映射:class Question(db.Model),完成发布函数。把发布内容保存到数据库。然后返回到首页。然后制作首页的显示列表,数据库查询结果传递到前端页面 Question.query.all(),前端页面循环显示整个列表。完成问答详情页布局: 包含问答的全部信息评论区以往评论列表显示区。在首页点击问答标题,链接到相应详情页。做出一个整体框架后,我们开始完善里面的内容,显示评论次数、要求评论前登录、 尝试实现详情页面下的评论、密码保护、实现标签页导航等。后面基本上都是在完善这个项目了。
在这一整个学期的学习过程中,也会遇到许许多多的问题,例如一开始怎么也把东西存放不进数据库,后来在一步步检查才发现没有在HTML中加上<from>标签;还有在某个单词拼写错误,在html里会用颜色的不同来报错,这种情况还较好处理,但在JS代码中是不会提示你哪里出错,所以在编写过程中要多加细心谨慎。还有在夜间模式里的JS文件中的两张图片的后缀不一样,但是在代码中后缀写的又是相同的,这样就不成功了。类似这种小错误还有很多,这就告诉我们在写代码的时候一定要细心谨慎,要多加检查。其实在每一个功能可以实现的时候,自己的成就感油然而生,所以我们多去练习多去运用,少用复制粘贴、投机取巧,我们才能在编程道路上越走越远。
2、总结Python+Flask+MysqL的web建设技术过程
在这学期里,我学习了使用Python的Flask框架+MysqL搭建简单的web项目,实现了具有登录注册发布评论功能等的简单页面。以下是我这学期的学习成果和学习经验:
1、开始新建Flask项目
① 新建Flask项目。② 设置调试模式。③ 理解Flask项目主程序。④ 使用装饰器,设置路径与函数之间的关系。⑤ 使用Flask中render_template,用不同的路径,返回首页、登录员、注册页
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/')
def sy():
return render_template('sy.html')
@app.route('/dl/')
def dl():
return render_template('dl.html')
@app.route('/zc/')
def zc():
return render_template('zc.html')
if __name__ == '__main__':
app.run(debug=True)
2、连接数据库
① 数据库配置信息config.py② 建立mysql和app的连接③ 创建用户模型
config.py:
import os SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:@127.0.0.1:3306/dianying?charset=utf8' SQLALCHEMY_TRACK_MODIFICATIONS = False SECRET_KEY = os.urandom(24)
建立连接+创建模型:
from flask import Flask,request,render_template,redirect,url_for,session
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime
from sqlalchemy import or_,and_
from functools import wraps
from flask_sqlalchemy import SQLAlchemy
import config
app = Flask(__name__)
app.config.from_object(config)
db = SQLAlchemy(app)
class User(db.Model):
__tablename__='user'
id = db.Column(db.Integer,primary_key=TabError,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_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'))
db.create_all()
@app.route('/')
def sy():
context = {
'questions': Question.query.all()
}
return render_template('sy.html', **context)
if __name__ == '__main__':
app.run(debug=True)
数据库:

3、导航条。
制作一个自己的导航条,在导航条里有HTML头部元素:①<base> 定义了页面链接标签的默认链接地址 ②<style>定义了HTML文档的样式文件 ③<link>定义了一个文档和外部资源之间的关系,还有在这认识的CCS盒子模型。用来实现样式的美化,新建相应CSS文件,并链接到html文件中。还设计了相应的底部导航,底部导航是一些图片的相应友情链接。还有在完成登录之后,导航条也会随之发生改变。并要在主py文件上进行更新操作。
导航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/dh.css') }}">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <!-- 用了bootstrap标准导航,导入其css样式-->
<script src="{{ url_for('static',filename='js/dh.js') }}"></script>
</head>
{% block head %}
{% endblock %}
<nav class="navbar navbar-default" role="navigation"> <!-- class里的代码是显示导航框架 -->
<div class="navbar-header"> <!-- class里的代码是让导航内容显示在同一行 -->
<a href="http://127.0.0.1:5000/nr/"><img class="tubiao" id="tubiao" src="{{ url_for('static',filename='image/tb.jpg')}}"></a>
</div>
<form action="{{ url_for('cx') }}" method="get" class="navbar-form navbar-left" role="search"> <!-- class里的代码是让导航内容显示在一行上,并且navbar-left是让搜索框向左边靠-->
<div class="form-group">
<input type="text" class="form-control" placeholder="✍输入您感兴趣的" name="q">
</div>
<button type="submit" class="btn btn-default">查找</button>
</form>
<ul class="nav navbar-nav navbar-right" id="myBody">
<li ><img class="tupian" id="myOnOff" onclick="myswitch()" src="{{ url_for('static',filename='image/sun.png')}}"></li>
<li><a href="{{ url_for('sy') }}"><span class="glyphicon .glyphicon-home"></span> 首页</a></li>
{% if username %}
<li><a href="{{ url_for('gr',user_id=session.get("userid"),tag=1) }}">{{ username }}</a></li>
<li><a href='{{ url_for('tc') }}'>退出</a></li>
{% else %}
<li><a href="{{ url_for('zc') }}"><span class="glyphicon glyphicon-user"></span> 注册</a></li>
<li><a href="{{ url_for('dl') }}"><span class="glyphicon glyphicon-log-in"></span> 登录</a></li>
{% endif %}
<li><a href="{{ url_for('fk') }}"><span class="glyphicon .glyphicon-pencil"></span> 发表影评</a></li>
</ul>
</div>
</nav>
<body id="myBody">
{% block main %}
{% endblock %}
<nav class="dibu">
<a class="daohang" href="http://www.youku.com/"><img src="http://is4.mzstatic.com/image/thumb/Purple71/v4/71/04/5b/71045b9d-3687-f8cc-1457-7055b4e4ed44/source/512x512bb.png"width="50" height="50" alt="gzcc.cn"></a>
<a class="daohang" href="http://v.qq.com/?ptag=360.kuzhan"><img src="http://p2.img.cctvpic.com/nettv/newgame/cdn_pic/1956/mzm.zamlltui.png"width="50" height="50" alt="gzcc.cn"></a>
<a class="daohang" href="https://www.mgtv.com/"><img src="http://imga.mumayi.com/android/img_mumayi/2014/12/10/88/885578/icon/885578_5b92a.png"width="50" height="50" alt="gzcc.cn"></a>
<a class="daohang" href="http://www.iqiyi.com/?vfm=f_268_360d&fv=07668579fcb3b76994a863f602b0dce3"><img src="http://pic.paopaoche.net/up/2014-7/2014711152858.png"width="50" height="50" alt="gzcc.cn"></a>
<a class="daohang" href="http://www.pptv.com/"><img src="http://sr1.pplive.com/cms/19/45/23f41cc6977ca745cce69cdf92e4a1f9.png"width="50" height="50" alt="gzcc.cn"></a>
<a class="daohang" href="https://tv.sohu.com/"><img src="http://www.d9soft.com/uploadfile/2013/0718/20130718061513909.png"width="50" height="50" alt="gzcc.cn"></a>
<p>Copyright ©2017 silky-L</p>
</nav>
</body>
</html>
CSS文件:
.tupian{
50px;
height:50px;
}
.tubiao{
50px;
height:50px;
}
.dibu{
100%;
background-color:gainsboro;
position:fixed;
bottom:0;/**距离底部为0*/left:0;z-index:1;
text-align:center;
}
效果如图:
头部导航条:

底部导航条:

登录后的导航条:

4、开关灯功能。
在导航条里有一个开关灯的按钮,要是要这个按钮的功能实现,就要上一个JS文件。JS文件用来定义开关切换函数,在HTML里面用onclick函数调用。在导航的HTML里用url_for加载静态文件<script src="{{ url_for('static',filename='js/dh.js') }}"></script>。HTML+CSS+JS这三个文件组成了一个父模板,在其他页面也可以继承这个父模板,不用每一个页面都去制作一个导航条。
JS文件:
function myswitch() {
var oBody = document.getElementById("myBody");
var oOnoff = document.getElementById("myOnOff");
if(oOnoff.src.match("sun")){
oOnoff.src="../static/image/moon.jpg";
oBody.style.background="black";
oBody.style.color ="white";
}else{
oOnoff.src="../static/image/sun.png";
oBody.style.background="white";
oBody.style.color ="black";
}
}
效果如图:
开灯:

关灯:

5、注册与登录页面。
注册与登录页面也有三个文件组成,HTML+CSS+JS。在注册与登录页面上还增加了三种输出数据的方式:① 使用 document.write() 方法将内容写到 HTML 文档中。② 使用 window.alert() 弹出警告框。③ 使用 innerHTML 写入到 HTML 元素。在JS文件里定义JavaScript 函数。并在主py文件里进行更新操作。
在注册页面里,
1 js文件: onclick函数return True时才提交表单,return False时不提交表单。
2 html文件:
<form>中设置 action和method="post"
<input> 中设置 name
3 主py文件中:
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中的数据
判断用户名是否存在:存在报错
不存在,存到数据库中
5 redirect重定向到登录页
注册HTML:
{% extends 'dh.html' %}
{% block title %}
注册
{% endblock %}
{% block main %}
<link rel="stylesheet" type="text/css" href="../static/css/zc.css">
<script src="../static/js/zc.js"></script>
</head>
<body class="zcbg" background="{{ url_for('static',filename='../static/image/zcbg.jpg') }}">
<div class="box" >
<form action="{{url_for('zc')}}" method="post">
<div class="container" style=" 400px"align="center">
<div class="dl"><h2 align="center" style="margin-bottom: 0; 400px">注 ✉ 册</h2></div>
<div class="content" style="">
<div class="xx" align="center">
<p> </p><br>
用户账号:<input id="name" type="name"placeholder="请输入用户名" name="name"><br>
输入密码:<input id="password" type="password"placeholder="请输入密码" name="password"><br>
确认密码:<input id="againpass" type="password"placeholder="请再次输入密码" name="againpass">
<p> </p>
</div>
<div id="error_box"><br></div>
<p> </p>
<div class="an" >
<button onclick="myLogin()">注册</button>
<button type="button" onclick=window.alert("是否取消注册!")>取消</button>
</div>
</div>
</div>
</form>
</div>
</body>
</html>
{% endblock %}
JS文件:
function myLogin() {
var oUname = document.getElementById("name");
var oError = document.getElementById("error_box");
var opassword = document.getElementById("password");
var oAgainname = document.getElementById("againpass");
oError.innerHTML="<br>"
//name
if(oUname.value.length<6||oUname.value.length>20){
oError.innerText="☞用户名请输入6-20个字符";
return false;
}
else if ((oUname.value.charCodeAt(0)>=48)&&oUname.value.charCodeAt(0)<=57){
oError.innerText="✘用户名首字母不能为数字";
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(0)<97) || (oUname.value.charCodeAt(0)>122)){
oError.innerHTML="✘用户名只能是小写字母与数字";
return false;
}
}
//password
if(opassword.value.length<6||oAgainname.value.length>20){
oError.innerText="☛密码请输入6-20个字符内";
return false;
}
else if (password.value!= againpass.value) {
oError.innerHTML = "✘两次密码不一致"
return false;
}
window.alert("✌注册成功!\(^o^)/YES!")
return true;
}
效果如图:


登录功能完成:
1 js:设置:return
2 html:设置:form、input、onclick="return fnLogin()"
3 py:
@app.route设置methods:GET、POST
读取表单数据、查询数据库、用户名密码对、记住用户名、跳转到首页、用户名密码不对、提示相应错误。
session:从`flask`中导入`session`、设置`SECRET_KEY`、操作字典一样操作`session`:增加用户名`session['username']=`username
登录HTML:
{% extends 'dh.html' %}
{% block title %}
登录
{% endblock %}
{% block main %}
<link rel="stylesheet" type="text/css" href="../static/css/dl.css">
<script src="../static/js/dl.js"></script>
</head>
<body class="bg" background="{{ url_for('static',filename='../static/image/dlbg.jpg') }}"> {# 背景图 #}
<div class="box" >
<form action="{{url_for('dl')}}" method="post">
<div class="container" style=" 400px"align="center">
<div class="dl"><h2 align="center" style="margin-bottom: 0;400px">✉登 录✉</h2></div>{# 登录标题 #}
<div class="content"> {#登录框#}
<div class="xx" align="center">
<p> </p>
账 户:<input id="name" type="text"placeholder="请输入用户名" name="name"><br>
密 码:<input id="password" type="password"placeholder="请输入密码" name="password">
<p> </p>
</div>
<div id="error_box"><br></div>
<p> </p>
<div class="an" >
<button onclick="myLogin()">登录</button>
<button type="button" onclick=window.alert("是否取消登录!")>取消</button>
</div>
</div>
</div>
</form>
</div>
</body>
</html>
{% endblock %}
JS文件:
function myLogin() {
var oUname = document.getElementById("name");
var oError = document.getElementById("error_box");
var opassword = document.getElementById("password");
oError.innerHTML="<br>"
//name
if(oUname.value.length<6||oUname.value.length>20){
oError.innerText="☞用户名请输入6-20个字符";
return false;
}
else if ((oUname.value.charCodeAt(0)>=48)&&oUname.value.charCodeAt(0)<=57){
oError.innerText="✘用户名首字母不能为数字";
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(0)<97) || (oUname.value.charCodeAt(0)>122)){
oError.innerHTML="✘用户名只能是小写字母与数字";
return false;
}
}
//password
if(opassword.value.length<6||opassword.value.length>20){
oError.innerText="☛密码请输入6-20个字符内";
return false;
}
return true;
}
效果如图:


7、发布页面。
制作带label的文本输入区域的页面,实现发布功能。最后要在主py文件里进行更新操作。
1 在主py文件里编写要求登录的装饰器
from functools import wraps
def loginFirst(func): #参数是函数
@wraps(func)
def wrapper(*args, ** kwargs): #定义个函数将其返回
#要求登录
return func(*args, ** kwargs)
return wrapper #返回一个函数
2 应用装饰器,要求在发布前进行登录,登录后可发布。
@app.route('/question/',methods=['GET','POST'])
@loginFirst
def question():
3 建立发布内容的对象关系映射。
class Question(db.Model):
4 完成发布函数。
5 保存到数据库。
6 重定向到首页。
HTML:
{% extends 'dh.html' %}
{% block title %}
反馈页面
{% endblock %}
{% block head %}
<link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='../static/css/fk.css') }}">
{% endblock %}
{% block main %}
<body>
<div class="question-feedback">
<h2> 影评发布 </h2>
<form action="{{ url_for('fk') }}" method="post" >
<div class="question-control">
<div>
<label for="question">标题:</label>
<br>
<textarea class="form-control" rows="6" id="questionTitle" placeholder="请输入影评标题"
style="height: 50px" name="title" ></textarea>
</div>
<div>
<label for="questionDetail">评论:</label>
<br>
<textarea class="form-control" rows="6" id="questionDetail" placeholder="请描述你对电影的感受"
style="height: 130px" name="detail"></textarea>
</div>
<input type="checkbox" id="c1">发布影评<br>
</div>
<div class="submit-button">
<br>
<button type="submit" style="float:right" id="submit-button">发送</button>
</div>
</form>
</div>
</body>
{% endblock %}
效果如图:

8、首页列表。
在影评发布后,会显示在首页的列表上。1 首页列表显示全部问答:将数据库查询结果传递到前端页面 Question.query.all() 2 前端页面循环显示整个列表。 3 问答排序。最后并在主py文件上进行更新操作。
首页HTML:
{% extends 'dh.html' %}
{% block title %}
首页
{% endblock %}
{% block head %}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="../static/css/sy.css">
{% endblock %}
{% block main %}
<body class="sybg" background="{{ url_for('static',filename='../static/image/sybg.jpg') }}">
<div class="nr-box">
<ul class="list-group">
{% for foo in questions %}
<li class="list-group-item">
<img style=" 30px" src="{{ url_for('static',filename='../static/image/tx.jpg') }}" alt="64">
<a href="{{ url_for('gr',user_id=foo.author.id,tag=1) }}">{{ foo.author.username }}</a><br>
<a href="{{ url_for('xq',question_id = foo.id) }}">题目:{{ foo.title }}</a><br>
<p>影评:{{ foo.detail }}</p><br>
<span class="badge" style="margin-left: 60%">{{ foo.creat_time }}发布时间</span>
<p style="margin-left: 25%"></p>
</li>
{% endfor %}
</ul>
</div>
</body>
{% endblock %}
效果如下:

9、详情页面。
制作详情页面,详情页布局:1 包含问答的全部信息 2 评论区 3 以往评论列表显示区。最后在主py文件上进行更新操作。
还要制作首页标题的标签做带参数的链接:{{ url_for('detail',question_id = foo.id) }}
1 在详情页将数据的显示在恰当的位置。
{{ ques.title}}
{{ ques.id }}{{ ques.creat_time }}
{{ ques.author.username }}
{{ ques.detail }}
2 建立评论的对象关系映射:
class Comment(db.Model):
__tablename__='comment'
3 尝试实现发布评论。
HTML:
{% extends 'dh.html' %}
{% block title %}
反馈详情
{% endblock %}
{% block head %}
<link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='../static/css/xq.css') }}">
{% endblock %}
{% block main %}
<div class="page-header">
<h3>问题:{{ ques.title }}<br>
<small>作者:{{ ques.author.username }}<br>
<span class="">
发布时间:{{ ques.creat_time }}
</span></small></h3>
<p class="lead">详情:{{ ques.detail }} </p>
<form role="form" action="{{ url_for('comment') }}" method="post">
<div class="form-group">
<textarea name="new_comment" class="form-control" rows="6" id="questionTitle" placeholder="请写下你的评论" style="height: 100px" ></textarea>
<input name="question_id" type="hidden" value="{{ ques.id }}">
<br>
<button type="submit" style="float:right" id="submit-button">发送</button>
</div>
</form></div>
<div class="pl-box">
<h4>评论区:
({{ ques.comments|length }})</h4><br>
<ul class="list-group">
{% for ques in ques.comments %}
<li class="list-group-item">
<img style=" 30px" src="{{ url_for('static',filename='../static/image/tx.jpg') }}" alt="64">
<a href="{{ url_for('gr',user_id=ques.author.id,tag=1) }}">{{ ques.author.username }}</a><br>
<p>评论详情:{{ ques.detail }}</p><br>
<span class="badge" style="margin-left: 60%">{{ ques.creat_time }}评论时间</span>
<p style="margin-left: 25%"></p>
</li>
{% endfor %}
</ul>
</div>
{% endblock %}
效果如图:


10、个人中心
先新建一个个人中心的导航页,个人中心的页面需要继承总的导航条。然后建立全部文章、全部评论、个人信息三个子页面继承个人中心的导航页。1 userbase.html,用<ul ><li role="presentation"> 实现标签页导航。2 让userbase.html继承父模板。然后三个子页面分别继承个人中心的导航页面。最后在主py文件中进行更新操作。
个人中心导航HTML:
{% extends 'dh.html' %}
{% block title %}
个人中心
{% endblock %}
{% block head %}
<style>
.nav_ul li{
float: left;
list-style: none;
margin: 10px;
border-bottom: antiquewhite;
}
</style>
{% endblock %}
{% block main %}
<ul class="nav nav-tabs">
<li role="presentation"><a href="{{ url_for('gr', user_id = user.id,tag='1') }}">全部问答</a></li>
<li role="presentation"><a href="{{ url_for('gr',user_id = user.id,tag='2') }}">全部评论</a></li>
<li role="presentation"><a href="{{ url_for('gr',user_id = user.id,tag='3') }}">个人信息</a></li>
</ul>
{% block user %}{% endblock %}
{% endblock %}
全部文章HTML:
{% extends 'gr-dh.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="margin: 10px">
{% for ques in question %}
<li class="list-group-item" style="word-wrap:break-word;">
<span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span>
<a href="#">{{ ques.author.username }}</a>
<span class="badge" style="margin-left: 60%">{{ ques.creat_time }}发布时间</span>
<p>{{ ques.detail }}</p>
</li>
{% endfor %}
</ul>
</div>
{% endblock %}
全部评论HTML:
{% extends 'gr-dh.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="margin: 10px">
{% for ques in comments %}
<li class="list-group-item">
<span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span>
<a href="#">{{ ques.author.username }}</a>
<span class="badge">{{ ques.create_time }}</span>
<p>{{ ques.detail }}</p>
</li>
{% endfor %}
</ul>
</div>
{% endblock %}
个人信息HTML:
{% extends 'gr-dh.html' %}
{% block user %}
<div class="page-header">
<h3><small>个人信息<span class="badge"></span></small></h3>
<ul class="list-group" style=" ">
<li class="list-group-item">用户:{{ username }}</li>
<li class="list-group-item">编号:{{ user.id }}</li>
<li class="list-group-item">文章数:{{ question|length }}</li>
<li class="list-group-item">评论数:{{ comments|length }}</li>
<p> </p>
</ul>
</div>
{% endblock %}
效果如图:



11、搜索功能。
修改父模板页面中搜索输入框所在的<form action="{{ url_for('search') }}" method="get">、<input name="q" type="text" placeholder="请输入关键字">
完成视图函数search()、获取搜索关键字:q = request.args.get('q’)、条件查询:qu = Question.query.filter(Question.title.contains(q)).order_by('-creat_time’)
加载查询结果:return render_template('index.html', question=qu)
组合条件查询:from sqlalchemy import or_, and_
主py文件:
@app.route('/cx/')
def cx():
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('sy.html',questions = ques)
导航页HTML:
<form action="{{ url_for('cx') }}" method="get" class="navbar-form navbar-left" role="search">
<div class="form-group">
<input type="text" class="form-control" placeholder="✍输入您感兴趣的" name="q">
</div>
<button type="submit" class="btn btn-default">查找</button>
</form>
12、密码保护。
1 更新User对象,设置对内的_password
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)
3 密码验证的方法:
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):
主py文件:
class User(db.Model):
__tablename__='user'
id = db.Column(db.Integer,primary_key=TabError,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_password): #密码验证
result = check_password_hash(self._password, row_password)
return result
@app.route('/dl/',methods=['GET','POST'])
def dl():
if request.method == 'GET':
return render_template("dl.html")
else:
usern = request.form.get('name')
password = request.form.get('password')
user = User.query.filter(User.username == usern).first()
if user:
if user.check_password(password):
session['user'] = usern
session['userid'] = user.id
session.permanent = True
return redirect(url_for('sy'))
else:
return '密码错误(〃>皿<)'
else:
return '用户不存在┌(。Д。)┐'
效果如图:

13、总的py文件:
from flask import Flask,request,render_template,redirect,url_for,session
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime
from sqlalchemy import or_,and_
from functools import wraps
from flask_sqlalchemy import SQLAlchemy
import config
app = Flask(__name__)
app.config.from_object(config)
db = SQLAlchemy(app)
class User(db.Model):
__tablename__='user'
id = db.Column(db.Integer,primary_key=TabError,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_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'))
#db.create_all()
# #增加
# user = User(username='123456',password = '456789')
# db.session.add(user)
# db.session.commit()
#
# #查询
# user =User.query.filter(User.username =='abcdef').first()
# print(user.username,user.password)
#
# #修改
# user =User.query.filter(User.username =='123456').first()
# user.password='abcdef'
# print(user.username,user.password)
# db.session.commit()
#
# #删除
# user =User.query.filter(User.username =='123456').first()
# print(user.username,user.password)
# db.session.delete(user)
# db.session.commit()
@app.route('/')
def sy():
context = {
'questions': Question.query.all()
}
return render_template('sy.html', **context)
@app.route('/xq/<question_id>')
def xq(question_id):
quest = Question.query.filter(Question.id == question_id).first()
return render_template('xq.html',ques = quest)
def loginFirst(func):
#行动前需要登录,定义装饰器
@wraps(func)
def wrapper(*args,**kwargs):
if session.get('user'):
return func(*args,**kwargs)
else:
return redirect(url_for('dl'))
return wrapper
@app.route('/comment/', methods=['POST'])
@loginFirst
def comment():
comment = request.form.get('new_comment')
ques_id = request.form.get('question_id')
author_id = User.query.filter(User.username == session.get('user')).first().id
comm = Comment(detail=comment, author_id=author_id, question_id=ques_id )
db.session.add(comm)
db.session.commit()
return redirect(url_for('xq', question_id=ques_id))
@app.route('/gr/<user_id>/<tag>')
@loginFirst
def gr(user_id,tag):
user=User.query.filter(User.id==user_id).first() #把信息存放到数据库里面
context={
'username':user.username,
'question':user.question,
'comments':user.comments,
'user':user
}
if tag == '1':
return render_template('wd.html',**context) #输出显示数据库里的信息
elif tag == '2':
return render_template('pl.html',**context)
else:
return render_template('zx.html', **context)
@app.route('/nr/')
def nr():
return render_template('nr.html')
@app.route('/dl/',methods=['GET','POST'])
def dl():
if request.method == 'GET':
return render_template("dl.html")
else:
usern = request.form.get('name')
password = request.form.get('password')
user = User.query.filter(User.username == usern).first()
if user:
if user.check_password(password):
session['user'] = usern
session['userid'] = user.id
session.permanent = True
return redirect(url_for('sy'))
else:
return '密码错误(〃>皿<)'
else:
return '用户不存在┌(。Д。)┐'
@app.context_processor
def mycontext():
usern=session.get('user')
if usern:
return {'username':usern}
else:
return{}
@app.route('/zc/',methods=['GET','POST'])
def zc():
if request.method == 'GET':
return render_template("zc.html")
else:
usern = request.form.get('name')
password = request.form.get('password')
user = User.query.filter(User.username == usern).first()
if user:
return '用户名已存在┗|*`0′*|┛ '
else:
user1 = User(username=usern, password=password)
db.session.add(user1)
db.session.commit()
return redirect(url_for('dl'))
@app.route('/tc/')
def tc():
session.clear();
return redirect(url_for('sy'))
def loginFirst(func):
#行动前需要登录,定义装饰器
@wraps(func)
def wrapper(*args,**kwargs):
if session.get('user'):
return func(*args,**kwargs)
else:
return redirect(url_for('dl'))
return wrapper
@app.route('/fk/',methods=['GET','POST'])
@loginFirst
def fk():
if request.method == 'GET':
return render_template('fk.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('sy'))
@app.route('/cx/')
def cx():
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('sy.html',questions = ques)
if __name__ == '__main__':
app.run(debug=True)
总结:以上就是本学期使用Python的Flask框架+MysqL完成简单的网页。Flask是一个使用Python编写的轻量级 Web 应用框架。感觉这一门科目是很有趣的,它运用的语言知识简洁易懂,当成功运行出来的时候,满满的成就感。虽然还是有很多地方还不是很理解,但是只要往后多了解,多练习,就会更好地掌握这些知识。
