期末作品检查
-
个人学期总结
在这个学期里,在老师带领下,我们学习了管理信息系统这门课程。由一开始懵懵懂懂的概念知识到后面基本熟悉的上机操作,这都离不开老师对我们一步步的指导。在这个课程中我发现,跟随老师的步伐,做出一个界面并不代表什么,而是需要课后多加熟悉,上手操作,才能算是掌握这门课程的核心。
在一开始接触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{ width:50px; height:50px; } .tubiao{ width:50px; height:50px; } .dibu{ width: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="width: 400px"align="center"> <div class="dl"><h2 align="center" style="margin-bottom: 0; width: 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="width: 400px"align="center"> <div class="dl"><h2 align="center" style="margin-bottom: 0;width: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="width: 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="width: 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 应用框架。感觉这一门科目是很有趣的,它运用的语言知识简洁易懂,当成功运行出来的时候,满满的成就感。虽然还是有很多地方还不是很理解,但是只要往后多了解,多练习,就会更好地掌握这些知识。