个人学期总结
在本学期我们学习了一门新语言python,他的语句不像那些java那么复杂,因为PY是
解释性语言,天生就有作为测试脚本语言的优势,语法简单,通俗易懂,可移植性好。对
于我们这些初学者而言还是比较容易上手的。老师一步步教我们去详细的操作,可以让我
们去完全的掌握这个功能怎么实现。
刚开始的时候我们学习了turtle库、条件、循环、函数的定义代码,后来学习了web、Flask
的制作。并可以实现网站父模板统一布局:头部导航条、底部图片导航、中间主显示区域布
局,注册、登录、注销、发布、列表显示详情页评论、列表显示个人中心搜索,条件组合
搜索的功能。在此过程中我们还学习到了css,就是样式。样式可以设置城我们自己喜欢的
样子,不同的风格。整个样式的布局那些可以体现每个人的不同水平。
在写代码的过程中,我也会遇到许多各种各样的大问题和小问题。比如某一行的代码
漏了,导致出错,或者是某个英文单词加多了个s,又出错。这样就会浪费了许多不必要的
时间。有时候子模版忘记去继承了父模版。就是因为自己太粗心才会导致了这些不必要的
错误出现一次又一次。所以我们在编辑代码的时候一定要细心一点,这样才能做的又快又
好。专心听老师讲的每一节课,才不会漏掉一些小细节。
所以说我们要多去实践,只有多实践才会出真理。要尝试动手,不要眼高手低。有些人
就是会觉得自己懂了,然后就觉得不必要去听了。可是当让他去动手做的时候却毫无头绪。
所以我们需要多思考,多动手。这样才能知道自己到底什么地方不懂,才能够对症下药去解
决问题。遇到困难要面对,不要觉得难就不去学了。其实多去思考最后还是能够去解决这些
问题的。
总结Python+Flask+MysqL的web建设技术过程
(1)展示登录的界面
这是登录页面的html代码
{% extends‘base.html‘ %} {% block title %}登陆{% endblock %} {% block head %} <link href="https:maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"rel="stylesheet"> <link href="{{ url_for(‘static‘,filename=‘css/login.css‘) }}" rel="stylesheet" type="text/css"> <link rel="stylesheet" type="text/css" href="{{ url_for(‘static‘,filename=‘css/base.css‘) }}"> <script src="{{ url_for(‘static‘,filename=‘js/login.js‘) }}"></script> <script src="{{ url_for(‘static‘,filename=‘js/base.js‘) }}"></script> {% endblock %} {% block main %} <div class="box"> <h2 style="text-align: center">登录</h2> <form action="{{url_for(‘login‘)}}" method="post"> <div class="input_box"> <input id="uname" type="text" placeholder="请输入用户名" name="username" style="width:350px;height:50px"> </div> <div class="input_box"> <input id="upass" type="password" placeholder="请输入密码" name="password" style="width:350px;height:50px"> </div> <br> <div id="error_box"><br></div> <div class="input_box"> <button onclick="return fnLogin()">登陆</button><br> <a class="link-forget cl-link-blue"href="{{ url_for(‘regist‘) }}" >忘记密码</a> <a class="link-forget cl-link-blue"href="{{ url_for(‘regist‘) }}">注册</a> </div> </form> </div> {% endblock %}
(2)注册页面
注册页面的html代码
{% extends‘base.html‘ %} {% block title %}注册{% endblock %} {% block head %} <link href="https:maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"rel="stylesheet"> <link href="{{ url_for(‘static‘,filename=‘css/login.css‘) }}" rel="stylesheet" type="text/css"> <link rel="stylesheet" type="text/css" href="{{ url_for(‘static‘,filename=‘css/base.css‘) }}"> <script src="{{ url_for(‘static‘,filename=‘js/regist.js‘) }}"></script> <script src="{{ url_for(‘static‘,filename=‘js/base.js‘) }}"></script> {% endblock %} {% block main %} <div class="box"> <h2 style="text-align: center">注册</h2> <form action="{{url_for(‘regist‘)}}" method="post"> <div class="input_box"> <input id="uname" type="text" placeholder="请输入用户名" name="username" style="width:350px;height:50px"> </div> <div class="input_box"> <input id="upass" type="password" placeholder="请输入密码" name="password" style="width:350px;height:50px"><br> <input id="upass1" type="password" placeholder="请重复输入密码" style="width:350px;height:50px"> </div> <div class="input_box"> <input id="nname" type="text" placeholder="请输入昵称" name="nickname" style="width:350px;height:50px"> </div> <br> <div id="error_box"><br></div> <div class="input_box"> <button onclick="return fnRegist()">注册</button><br> </div> </form> </div> {% endblock %}
(3)发布问答
发布问答的html
{% extends‘base.html‘ %} {% block title %}发布问题{% endblock %} {% block head %} <link href="https:maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"rel="stylesheet"> <link href="{{ url_for(‘static‘,filename=‘css/ask.css‘) }}" rel="stylesheet" type="text/css"> <link href="{{ url_for(‘static‘,filename=‘css/base.css‘) }}" rel="stylesheet" type="text/css"> <link href="{{ url_for(‘static‘,filename=‘css/login.css‘) }}" rel="stylesheet" type="text/css"> <script src="{{ url_for(‘static‘,filename=‘js/base.js‘) }}"></script> {% endblock %} <nav></nav> {% block main %} <div class="box"> <h2>发布问题</h2> <form action="{{url_for(‘ask‘)}}" method="post"> <div class="question"> <label for="title">问题</label> <textarea id="title" name="title" rows="1" clos="60"></textarea> </div> <div class="form-group"> <label for="detail">详情</label> <textarea class="form-group" id="detail" name="detail" rows="5" cols="60" ></textarea> </div> <div class="input-area"> <input type="submit" value="立即发布"></input> </div> </form> </div> {% endblock %}
(4)详情页
详情页的html
{% extends ‘base.html‘ %} {% block title%}问答详情{% endblock %} {% block head %} <!-- 引入 Bootstrap --> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" type="text/css" href="{{ url_for(‘static‘,filename=‘css/detail.css‘) }}"> <script src="{{ url_for(‘static‘,filename=‘js/base.js‘) }}"></script> {% endblock %} <nav></nav> {% block main %} <div class="container"> <div class="row clearfix"> <div class="page-header"> <h3>标题:{{ques.title}} <select> <option>收藏</option> <option>点赞</option> </select><br> <!--<small ><a href="{{url_for(‘usercenter‘,user_id=ques.anthor_id,tag=3)}}">{{ques.author.username}}</a>--> <a class="author" href="{{url_for(‘usercenter‘,user_id=ques.author_id,tag=1)}}">{{ques.author.username}}</a> <span class="badge">{{ques.create_time}}</span></small> </h3> </div> <p>内容:{{ques.detail}}</p> <hr> <form action="{{url_for(‘comment‘)}}"method="post" style="margin:20px"> <div class="form-group"> <textarea name="new_comment"class="form-control"rows="5"id="new-comment"placeholder="write your comment"></textarea> <input name="question_id" type="hidden" value="{{ques.id}}"> </div> <button type="submit"class="btn btn-default">发送</button> </form> <!--评论数目--> <h4>评论:({{ ques.comments|length }})</h4> </div> </div> <ul class="list-group"style="margin:10px"> {%for foo in ques.comments%} <li class="list-group-item"> <span class="glyphicon lgyphicon-heart-empty" aira-hidden="true"></span> <a href="{{url_for(‘usercenter‘,user_id=foo.author.id,tag=1)}}">{{foo.author.username}}</a> <span class="badge">{{foo.create_time}}</span> <p>{{foo.detail}}</p> </li> {%endfor%} </ul> {% endblock %}
(5)夜间模式
夜间模式的html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>夜晚模式</title> <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="white"; }else{ oOnoff.src="http://www.runoob.com/images/pic_bulbon.gif"; oBody.style.background="white"; oBody.style.color="black"; } } </script> </head> <body id="myBody"> <img id="myOnOff" onclick="mySwitch()" src="http://www.runoob.com/images/pic_bulbon.gif" width="40px"> <script>document.write(Date())</script> </body> </html>
(6)个人中心的父模版html
{% extends ‘user.html‘%} {% 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="{{ url_for(‘static‘,filename=‘css/detail.css‘) }}"> <script src="{{ url_for(‘static‘,filename=‘js/base.js‘) }}"></script> {% endblock %} {% block user%} <div class="page-header"> <h3> <span class="glyphicon glyphicon-user" aria-hidden="true"></span>{{username}}<br><small>全部问答<span class="bagde"></span></small> </h3> <ul class="list-group" > {%for foo in questions%} <li class="list-group-item"> <span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span> <a href="{{url_for(‘usercenter‘,user_id=foo.author_id,tag=1)}}">{{foo.author.username}}</a> <span class="badge">{{foo.create_time}}</span> <p>文章标题:{{ foo.title }}</p> <p>文章内容:{{foo.detail}}</p> </li> {% endfor %} </ul> </div> <div class="page-header" > <h3> <span class="glyphicon glyphicon-user" aria-hidden="true"></span>{{username}}<br><small>全部评论<span class="bagde"></span></small> </h3> <ul class="list-group" > {%for foo in comments%} <li class="list-group-item"> <span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span> <a href="{{url_for(‘usercenter‘,user_id=foo.author_id,tag=1)}}">{{foo.author.username}}</a> <span class="badge">{{foo.create_time}}</span> <p>文章标题:{{ foo.title }}</p> <p>评论内容:{{foo.detail}}</p> </li> {% endfor %} </ul> </div> <div class="page-header" > <h3> <span class="glyphicon glyphicon-user" aria-hidden="true"></span>{{username}}<br><small>个人信息<span class="bagde"></span></small> </h3> <ul class="list-group"> <li class="list-group-item">用户:{{ username }}</li> <li class="list-group-item">昵称:xxx</li> <li class="list-group-item">问答条数:{{ questions|length }}</li> <li class="list-group-item">评论条数:{{ comments|length }}</li> </ul> </div> {% endblock %}
(7)全部问答
全部问答的html
{% extends ‘usercenter.html‘%} {%block user%} <div class="page-header"> <h3> <span class="glyphicon glyphicon-user" aria-hidden="true"></span>{{username}}<br><small>全部问答<span class="bagde"></span></small> </h3> <ul class="list-group" > {%for foo in questions%} <li class="list-group-item"> <span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span> <a href="{{url_for(‘usercenter‘,user_id=foo.author_id,tag=1)}}">{{foo.author.username}}</a> <span class="badge">{{foo.create_time}}</span> <p>文章标题:{{ foo.title }}</p> <p>文章内容:{{foo.detail}}</p> </li> {% endfor %} </ul> </div> {% endblock%}
(8)全部评论
全部评论的html
{% extends ‘usercenter.html‘%} {%block user%} <div class="page-header" > <h3> <span class="glyphicon glyphicon-user" aria-hidden="true"></span>{{username}}<br><small>全部评论<span class="bagde"></span></small> </h3> <ul class="list-group" > {%for foo in comments%} <li class="list-group-item"> <span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span> <a href="{{url_for(‘usercenter‘,user_id=foo.author_id,tag=1)}}">{{foo.author.username}}</a> <span class="badge">{{foo.create_time}}</span> <p>文章标题:{{ foo.title }}</p> <p>评论内容:{{foo.detail}}</p> </li> {% endfor %} </ul> </div> {% endblock%}
(9)个人信息
个人信息的html
{% extends ‘usercenter.html‘%} {%block user%} <div class="page-header" > <h3> <span class="glyphicon glyphicon-user" aria-hidden="true"></span>{{username}}<br><small>个人信息<span class="bagde"></span></small> </h3> <ul class="list-group"> <li class="list-group-item">用户:{{ username }}</li> <li class="list-group-item">昵称:xxx</li> <li class="list-group-item">问答条数:{{ questions|length }}</li> <li class="list-group-item">评论条数:{{ comments|length }}</li> </ul> </div> {% endblock%}
(10)首页父模版的html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title> {% block title %}{% endblock %} 页面 </title> <style> p.sansserif{font-family:"Comic Sans MS", cursive, sans-serif} </style> {% block head %} <!--引入bootstrap--> <link href="https:maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"rel="stylesheet"> <link rel="stylesheet" type="text/css" href="{{ url_for(‘static‘,filename=‘css/base.css‘) }}"> <script src="{{ url_for(‘static‘,filename=‘js/base.js‘) }}"></script> <link rel="stylesheet" type="text/css" href="../static/css/tu.css"> {% endblock %} </head> <body id="myBody"> <nav> <div class="img"> <img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1515127601934&di=c0de8be320080667a285226dc31f1fe6&imgtype=0&src=http%3A%2F%2Fpic.58pic.com%2F58pic%2F17%2F65%2F65%2F58PIC58PICW58PICVXF_1024.jpg" style="width:100%;height:350px" ><br> </div> <img id="myOnOff" onclick="mySwitch()" src="http://www.runoob.com/images/pic_bulbon.gif" width="25px"> <ul> <a href="{{ url_for(‘base‘) }}">首页</a> <a href="{{ url_for(‘login‘) }}">登录</a> <a href="{{ url_for(‘regist‘) }}">注册</a> <a href="{{ url_for(‘ask‘) }}">发布问题</a> <a href="{{url_for(‘logout‘)}}">注销</a> </ul><br> <form action="{{url_for(‘search‘)}}" method="get"> <input name="q" type="text" placeholder="请输入关键字"> <button type="submit">搜索</button> </form> <div class="zy"> {% if username %} <a href=""><p class="sansserif">{{ username }},您好</p></a> <li><a href="{{url_for(‘logout‘)}}">注销</a></li> {% else %} {% endif %} </div> </nav> {% block main %} <div> <ul class="list-group" style="align-content: center"> {%for foo in questions %} <li class="list-group-item" > <span class="glyphicon glyphicon-leaf"aria-hidden="true"></span> <a href="{{ url_for(‘detail‘,question_id=foo.id) }}" class="title">标题:{{ foo.title }}</a><br> <p class="detail">内容:{{ foo.detail }}</p> <a class="author" href="{{url_for(‘usercenter‘,user_id=foo.author_id,tag=1)}}">{{foo.author.username}}</a>评论:({{ foo.comments|length }})<br> <span class="badge">{{foo.create_time}}</span> </li> {% endfor %} </ul> </div> {% endblock %} <div class="area"> </div> <footer> <div class="footer_box"> <img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1515125656787&di=5d6eb7fa3e307a8574f5720179a18d59&imgtype=0&src=http%3A%2F%2Fpic1.16pic.com%2F00%2F51%2F75%2F16pic_5175300_b.jpg" style="width:50%;height:300px" ><br> Copyright@2017 个人版权,版权所有 作者:黄乐仪 </div> </footer> </body> </html>
①.安装与配置:
下载安装MySQL数据库
下载安装Navicat for MySQL
下载安装第三方库MySQL-python 中间件(pip install flask-sqlalchemy (Python的ORM框架SQLAlchemy))
②.运用可是化工具Navicat for MySQL创建数据库
③.数据库配置信息config.py
import os DEBUG=True SECRET_KEY=os.urandom(24) DIALECT=‘mysql‘ DRIVER=‘mysqldb‘ USERNAME=‘root‘ PASSWORD=‘ROOT‘ HOST=‘127.0.0.1‘ PORT=‘3306‘ DATABASE=‘misdb‘ SQLALCHEMY_DATABASE_URI = ‘mysql+pymysql://root:123456@localhost:3306/misdb?charset=utf8‘ SQLALCHEMY_TRACK_MODIFICATIONS = False
建立mysql和app的连接
from flask import Flask from flask_sqlalchemy import SQLAlchemy import config app = Flask(__name__) # 创建Flask对象 app.config.from_object(config) # 关联config.py文件进来 db = SQLAlchemy(app) # 建立和数据库的关系映射 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‘)) fabu_id = db.Column(db.Integer, db.ForeignKey(‘fabu.id‘)) creat_time = db.Column(db.DateTime, default=datetime.now) detail = db.Column(db.Text, nullable=False) fabu = db.relationship(‘Fabu‘, backref=db.backref(‘comments‘, order_by=creat_time.desc)) # order_by=creat_time.desc按时间降序 author = db.relationship(‘User‘, backref=db.backref(‘comments‘)) db.create_all() # 测试是否连接成功 @app.route(‘/lin/‘) # 跳转测试。 def lin(): return ‘lin‘ if __name__ == ‘__main__‘: app.run(debug=True)
创建用户模型
class User(db.Model): # 创建类User ... class Fabu(db.Model): ... class Comment(db.Model): ...
通过用户模型,对数据库进行增删改查
# 插入功能 user = User(username=‘15‘,password=‘12‘) db.session.add(user) db.session.commit() # 查询功能 user=User.query.filter(User.username=="15").first() print(user.username,user.password) # 修改功能 user=User.query.filter(User.username=="15").first() user.password=‘888‘ db.session.commit() # 删除功能 user=User.query.filter(User.username=="15").first() db.session.delete(user) db.session.commit()
完成注册功能
# 跳转注册。 @app.route(‘/zhuce/‘, methods=[‘GET‘, ‘POST‘]) # methods定义它有两种请求方式,因为它在表单的请求是post,类似我们在idea中的sava请求模式 def zhuce(): if request.method == ‘GET‘: return render_template(‘zhuce.html‘) else: username = request.form.get(‘user‘) # post请求模式,安排对象接收数据 password = request.form.get(‘pass‘) nickname = request.form.get(‘nickname‘) user = User.query.filter(User.username == username).first() # 作查询,并判断 if user: return u‘该用户已存在‘ else: user = User(username=username, password=password, nickname=nickname) # 将对象接收的数据赋到User类中,即存到数据库 db.session.add(user) # 执行操作 db.session.commit() return redirect(url_for(‘denglu‘)) # redirect重定向
完成登录功能
# 跳转登陆。 @app.route(‘/denglu/‘, methods=[‘GET‘, ‘POST‘]) # methods定义它有两种请求方式 def denglu(): if request.method == ‘GET‘: return render_template(‘denglu.html‘) else: username = request.form.get(‘user‘) # post请求模式,安排对象接收数据 password = request.form.get(‘pass‘) user = User.query.filter(User.username == username).first() # 作查询,并判断 if user: # 判断用户名 if user.check_password(password): # 判断密码 session[‘user‘] = username # 利用session添加传回来的值username session.permanent = True # 设置session过期的时间 return redirect(url_for(‘daohang‘)) else: return u‘用户密码错误‘ else: return u‘用户不存在,请先注册‘
上下文处理器中可以在任何模板页面中调用
@app.context_processor # 上下文处理器,定义变量然后在所有模板中都可以调用,类似idea中的model def mycontext(): user = session.get(‘user‘) if user: return {‘sessionusername‘: user} # 包装到username,在所有html模板中可调用 else: return {} # 返回空字典,因为返回结果必须是dict
用上下文处理器app_context_processor定义函数,把登陆时定义的session get进来
@app.context_processor # 上下文处理器,定义变量然后在所有模板中都可以调用,类似idea中的model def mycontext(): user = session.get(‘user‘) if user: return {‘sessionusername‘: user} # 包装到username,在所有html模板中可调用 else: return {} # 返回空字典,因为返回结果必须是dict
完成注销功能session并跳转
# 跳转注销。 @app.route(‘/logout‘) def logout(): session.clear() # 注销时删除所有session return redirect(url_for(‘daohang‘))
.编写请求登录的装饰器
# 跳转某页面之前先进行登录。定义decorator可以增强函数功能,装饰器本身是函数,入参是函数,返回值也是函数 def loginFirst(fabu): @wraps(fabu) # 加上wraps,它可以保留原有函数的__name__,docstring def wrapper(*args, **kwargs): # 定义wrapper函数将其返回,用*args, **kwargs把原函数的参数进行传递 if session.get(‘user‘): # 只有经过登陆,session才能记住并get到值 return fabu(*args, **kwargs) else: return redirect(url_for(‘denglu‘)) return wrapper
实现发布评论,并显示评论区
# 跳转评论 @app.route(‘/comment/‘, methods=[‘POST‘]) @loginFirst # 装饰器,跳转某页面之前先进行登录 def comment(): detail = request.form.get(‘pinglun‘) # post请求模式,安排对象接收数据 author_id = User.query.filter(User.username == session.get(‘user‘)).first().id fabu_id = request.form.get(‘fa_id‘) comment = Comment(detail=detail, author_id=author_id, fabu_id=fabu_id) # 将对象接收的数据赋到Comment类中,即存到数据库 db.session.add(comment) # 执行操作 db.session.commit() # 提交到数据库 return redirect(url_for(‘fabuview‘, fabu_id=fabu_id)) # 重定向到fabuview请求时要带fabu_id
个人中心—视图函数带标签页面参数tag(在if判断时判断tag,可以三个页面跳转同一请求函数)
# 跳转用户详情 @app.route(‘/yonghu/<username_id>/<tag>‘) # 为了把页面分开,我们在html页面传了一个tag参数 def yonghu(username_id, tag): user = User.query.filter(User.id == username_id).first() context = { ‘userid‘: user.id, ‘username‘: user.username, ‘fabus‘: user.fabu, ‘comments‘: user.comments } # 根据tag的不同去到不同页面,一个请求跳转3个不同页面 if tag == ‘1‘: return render_template(‘yonghu1.html‘, **context) elif tag == ‘2‘: return render_template(‘yonghu2.html‘, **context) else: return render_template(‘yonghu3.html‘, **context)
实现导航条中的搜索功能
# 跳转首页搜索 @app.route(‘/search/‘) def search(): sousuo = request.args.get(‘sousuo‘) # args获取关键字,区别form fabus = Fabu.query.filter( or_( # 两种查询条件 Fabu.title.contains(sousuo), # contains模糊查 Fabu.detail.contains(sousuo) ) ).order_by(‘-creat_time‘) return render_template(‘daohang.html‘, fabus=fabus) # fabus要和原首页数据模型一样
密码保护
from werkzeug.security import generate_password_hash,check_password_hash _password = db.Column(db.String(200), nullable=False) # 密码加密内部使用 @property # 定义函数,需要用属性时可以用函数代替 def password(self): # 密码加密外部使用 return self._password @password.setter def password(self,row_password): # 密码进来时进行加密,generate_password_hash是一个密码加盐哈希函数,生成的哈希值可通过check_password_hash()进行验证。 self._password = generate_password_hash(row_password) def check_password(self,row_password): # check_password_hash函数用于验证经过generate_password_hash哈希的密码。若密码匹配,则返回真,否则返回假。 result = check_password_hash(self._password,row_password) return result