一、个人学期总结
本学期从一开始便接触Python语言,感觉Python还是比较容易上手的。从一开始简单的几何图形制作到最后网页数据库的链接实现,这个过程其实不算长,不过也因此最后作业的完成也比较简单。如果想从事这方面的工作,这学期所学的知识最多也只能是算基础,让自己在未来想深入学习Python有能力能自己学习更高级的功能。
对于这学期学习的,还是以最后这个大作业作为讲述的内容吧!毕竟这个才算得上比较完整。
从这个作业的实现来看,本学期老师教的知识基本上都能掌握,尽管自己可能无法全部记住,但是看着以前的作业自己也能知道相应的功能应该如何去实现。一边学习一边做出相应功能程序并提交的这种授课方式对于我们来说是更好的,相当于我们在上课的同时也将笔记给做了。在最后自己去做一整份作业的时候也有功能实现参考。
二、总结Python+Flask+MysqL的web建设技术过程,标准如下:
1、即是对自己所学知识的梳理
2、也可作为初学入门者的简单教程
3、也可作为自己以后复习的向导
4、也是一种向外展示能力的途径
答:本次期末答辩网页的实现是通过Python语言,创建本地数据库并链接两者来一起实现的。Python语言可经由PyCharm这个软件来编写,Flask的导入可以方便我们编写程序,因为一些简单的程序它都会自动生成,而不用自己再一个一个代码去码。创建数据库的原因是为了实现我们的一些相应功能的操作。像注册用户我们需要把信息传入数据库并保存下来,而登录操作我们又需要去数据库里查找是否有这个用户,并将这个用户的所有信息予以展示。这些都需要用到数据库,而数据库的创建除了用cmd之外,我们还可以用Navicat for MySQL这个可视化软件来创建,当然我偷懒的方式就是直接用这个软件来实现我所有数据库的操作的。
app.config.from_object(config) # 关联config.py文件进来
db = SQLAlchemy(app) # 建立和数据库的关系映射
class User(db.Model): # 创建类User
__tablename__ = ‘user‘ # 类对应的表名user
id = db.Column(db.Integer, primary_key=True, autoincrement=True) # autoincrement自增长
username = db.Column(db.String(20), nullable=False) # nullable是否为空
_password = db.Column(db.String(200), nullable=False) # 密码加密内部使用
nickname = db.Column(db.String(20), nullable=True)
在数据库中创建相对应的表,设置表格的id自动生成,用户名不能为空,密码加密等,相应代码都有注释,下面雷同。
@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‘用户不存在,请先注册‘
在post请求模式,安排对象接收数据这里,将网页所输入的信息接收,然后传入数据库查询并判断用户名和密码,如果对了则登录,错了便提示。
@app.route(‘/zhuce/‘, methods=[‘GET‘, ‘POST‘])
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)
db.session.add(user)
db.session.commit()
return redirect(url_for(‘denglu‘)) # redirect重定向
和登录类似,不过注册只对用户名进行查询是否有错,没错则将数据传入并保存与数据库。最后跳转至登录界面。
def loginFirst(fabu):
@wraps(fabu) # 加上wraps,它可以保留原有函数的__name__,docstring
def wrapper(*args, **kwargs): # 定义wrapper函数将其返回,用*args, **kwargs把原函数的参数进行传递
if session.get(‘user‘):
return fabu(*args, **kwargs)
else:
return redirect(url_for(‘denglu‘))
return wrapper
@app.route(‘/fabu/‘, methods=[‘GET‘, ‘POST‘])
@loginFirst # 将decorator定义的增强函数放在待增强函数定义的上面
def fabu():
if request.method == ‘GET‘:
return render_template(‘fabu.html‘)
else:
title = request.form.get(‘title‘) # post请求模式,安排对象接收数据
detail = request.form.get(‘detail‘)
author_id = User.query.filter(
User.username == session.get(‘user‘)).first().id
fabu = Fabu(title=title, detail=detail, author_id=author_id) # 将对象接收的数据赋到Fabu类中,即存到数据库
db.session.add(fabu)
db.session.commit()
return redirect(url_for(‘daohang‘)) # redirect重定向
若能获取到用户信息则发布问答,若没能获取用户信息则跳转至登录界面。
@app.route(‘/fabuview/<fabu_id>‘) def fabuview(fabu_id): fa = Fabu.query.filter(Fabu.id == fabu_id).first() comments = Comment.query.filter(Comment.fabu_id == fabu_id).all() return render_template(‘fabuview.html‘, fa=fa, comments=comments)
@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)
db.session.add(comment) # 执行操作
db.session.commit() # 提交到数据库
return redirect(url_for(‘fabuview‘, fabu_id=fabu_id)) # 重定向到fabuview请求时要带fabu_id
跳转至发布内容页,显示出发布内容,下面则可以进行评论。评论也会提交进数据库。
@app.route(‘/yonghu/<username_id>/<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)
更具用户id进入到相对应的用户界面,并显示出该用户的基本信息。
@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要和原首页数据模型一样
查询框可以查询标题或者内容,实现了模糊查询。
以下是HTML、CSS、JS的代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> 首页 {% block denglutitle %}{% endblock %} {% block zhucetitle %}{% endblock %} {% block tupiantitle %}{% endblock %} {% block fabutitle %}{% endblock %} {% block fabu_viewtitle %}{% endblock %} {% block yonghufathertitle %}{% endblock %} </title> <link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css"> <link rel="stylesheet" href="{{ url_for(‘static‘,filename=‘css/daohang.css‘) }}"> <script src="http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script> <script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script> <script src="{{ url_for(‘static‘,filename=‘js/dengpao.js‘) }}"></script> {% block dengluhead %}{% endblock %} {% block zhucehead %}{% endblock %} {% block tupianhead %}{% endblock %} {% block fabuhead %}{% endblock %} {% block fabu_viewhead %}{% endblock %} {% block yonghufatherhead %}{% endblock %} </head> <body id="mybody"> <nav class="navbar navbar-default" role="navigation"> <div class="container-fluid"> <div class="navbar-header"> <a class="navbar-brand" href="{{ url_for(‘daohang‘) }}">首页</a> </div> <div> <ul class="nav navbar-nav navbar-right"> {% if sessionusername %} <li><a href="http://127.0.0.1:5000/yonghu" onclick="">{{ sessionusername }}</a></li> <li><a href="{{ url_for(‘logout‘) }}" onclick=""><span class="glyphicon glyphicon-log-out"></span> 注销</a></li> {% else %} <li><a href="{{ url_for(‘denglu‘) }}" onclick=""><span class="glyphicon glyphicon-log-in"></span> 登录</a> </li> <li><a href="{{ url_for(‘zhuce‘) }}" onclick=""><span class="glyphicon glyphicon-user"></span> 注册</a></li> {% endif %} </ul> </div> <div> <ul class="nav navbar-nav"> <li><a href="{{ url_for(‘fabu‘) }}" onclick="">发布</a></li> </ul> </div> <form class="form-inline" role="form" action="{{ url_for(‘search‘) }}" method="get"> <div class="form-group"> <label class="sr-only" for="sousuo">名称</label> <input type="text" class="form-control" name="sousuo" id="sousuo" placeholder="请输入内容"> <input type="submit" value="搜索" class="btn btn-default" onclick=""> </div> </form> </div> </nav> {% block daohangbody %} <div class="container"> <div class="row clearfix"> <div class="col-md-4 column s1"></div> <div class="col-md-4 column s1"> <h1 class="text-center">发布</h1> <ul class="list-unstyled"> {% for foo in fabus %} <li class="list-group-item-success"> <a href="{{ url_for(‘yonghu‘,username_id=foo.author_id,tag=1) }}"><span class="glyphicon glyphicon-fire"></span>{{ foo.author.username }}</a> <h4 class="text-center"><a href="{{ url_for(‘fabuview‘,fabu_id=foo.id) }}">{{ foo.title }}</a></h4> <span class="badge pull-right">{{ foo.creat_time }}</span> <br> <p>{{ foo.detail }}</p> </li> {% endfor %} </ul> </div> <div class="col-md-4 column"></div> </div> </div> {% endblock %} <footer> <div class="container-fluid"> <div class="navbar-header"> <a class="navbar-header" href="https://www.360kan.com/ctUbkbcLWLYz3ED.html" style="color:blue">火影忍者选集</a> </div> </div> </footer> </body> </html>
首页链接到其他HTML页面,并起到做父模板的作用。链接CSS、JS,实现其中的样式和功能。其中有头部导航和底部导航。
#mybody{
background-image: url("../img/首页.jpg"); /*背景图*/
background-size: cover; /*背景图拉伸*/
padding-bottom: 100px; /*尾部导航距离内容宽度*/
}
#navtop{
margin-top: 30px; /*头部导航距离内容宽度*/
}
footer{
margin-top:50%;
margin-left: 50%;
}
这里是设置首页的样式,footer设置了首页可上下滑动且底部导航居中。
function fnRegistration() { var uSer = document.getElementById("user"); var pAss = document.getElementById("pass"); var aGain = document.getElementById("again"); var oError = document.getElementById("error_box"); var isError = true; oError.innerHTML = "<br>"; 验证用户名 if (uSer.value.length < 6 || uSer.value.length > 20) { oError.innerHTML = "用户名只能6-20位"; isError = false; return isError; } else if ((uSer.value.charCodeAt(0) >= 48) && (uSer.value.charCodeAt(0) <= 57)) { oError.innerHTML = "用户名首字母不能是数字"; isError = false; return isError; } else for (var i = 0; i < uSer.value.length; i++) { if ((uSer.value.charCodeAt(i) < 48) || (uSer.value.charCodeAt(i) > 57) && (uSer.value.charCodeAt(i) < 97) || (uSer.value.charCodeAt(i) > 122)) { oError.innerHTML = "用户名只能由数字和字母组成"; isError = false; return isError; } } // 验证密码 if (pAss.value.length < 6 || pAss.value.length > 20) { oError.innerHTML = "密码只能6-20位"; isError = false; return isError; } // 验证再次输入的密码 if (aGain.value != pAss.value) { oError.innerHTML = "密码不一致"; isError = false; return isError; } // 验证弹框 window.alert("注册成功!"); return true; }
实现了注册时用户名、密码的限制条件,并二次 确认密码是否正确。
{% extends ‘daohang.html‘ %} {% block zhucetitle %}注册{% endblock %} {% block zhucehead %} <link rel="stylesheet" type="text/css" href="{{ url_for(‘static‘,filename=‘css/denglu.css‘) }}"> <script src="{{ url_for(‘static‘,filename=‘js/edit.js‘) }}"></script> {% endblock %} {% block daohangbody %} <div id="container" style="margin-left: auto;margin-right: auto"> <div id="header"><h2 align="center">注册</h2></div> <div id="content"> <form action="{{ url_for(‘zhuce‘) }}" method="post"><br> <p align="center">用户名称:</p> <p align="center"> <input type="text" name="user" id="user" placeholder="请输入用户名"> </p> <p align="center">密码:</p> <p align="center"> <input type="password" name="pass" id="pass" placeholder="请输入密码"> </p> <p align="center">确认密码:</p> <p align="center"> <input type="password" name="again" id="again" placeholder="再次输入密码"> </p> <div id="error_box"><br></div> <p align="center"> <input type="submit" value="注册" onclick="return fnRegistration()"> </p> </form> </div> </div> {% endblock %}
继承首页,并添加一些需要的内容。简单的都可以在runoob这个网站这里拿到。样式里面还有css当中的组成。
{% extends ‘daohang.html‘ %} {% block denglutitle %}登录{% endblock %} {% block dengluhead %} <link rel="stylesheet" type="text/css" href="{{ url_for(‘static‘,filename=‘css/denglu.css‘) }}"> <script src="{{ url_for(‘static‘,filename=‘js/edit.js‘) }}"></script> {% endblock %} {% block daohangbody %} <div id="container" style="margin-left: auto;margin-right: auto"> <div id="header"><h2 align="center">请登录</h2></div> <div id="content"> <form action="{{ url_for(‘denglu‘) }}" method="post" align="center"><br> 用户名称:<input type="text" name="user" id="user" placeholder="请输入用户名"> <br> 密 码:<input type="password" name="pass" id="pass" placeholder="请输入密码"> <br> <div id="error_box"><br></div> <input type="submit" value="登录" onclick="return fnLogin()">  <button><a href="{{ url_for(‘zhuce‘) }}">注册</a> </button> </form> </div> </div> {% endblock %}
类似于注册界面,表面的展示效果大同小异。
{% extends ‘daohang.html‘ %} {% block fabutitle %}发布{% endblock %} {% block fabuhead %} <link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css"> <script src="http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script> <script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script> {% endblock %} {% block daohangbody %} <form role="form" action="{{ url_for(‘fabu‘) }}" method="post"> <div class="col-md-4 column"></div> <div class="form-group col-md-4 column"> <label for="title">标题</label> <textarea class="form-control" rows="1" id="title" name="title"></textarea> <label for="detail">详情</label> <textarea class="form-control" rows="10" id="detail" name="detail"></textarea> <div id=""><br></div> <input type="submit" value="发布" class="btn btn-default" onclick=""> </div> <div class="col-md-4 column"></div> </form> {% endblock %}
这是发布问答页面。
{% extends ‘daohang.html‘ %} {% block fabu_viewtitle %}发布内容{% endblock %} {% block fabu_viewhead %}{% endblock %} {% block daohangbody %} <div class="col-md-4 column "></div> <div class="col-md-4 column "> <h2 href="#" class="text-center">{{ fa.title }}</h2> <br> <p class="text-center"> <a href="{{ url_for(‘yonghu‘,username_id=fa.author_id,tag=1) }}"> <small>{{ fa.author.username }}</small> </a>    <span class="pull-center"><small>{{ fa.creat_time }}</small></span> </p> <hr> <p>{{ fa.detail }}</p> <hr> <form action="{{ url_for(‘comment‘) }}" method="post"> <div class="form-group"> <textarea name="pinglun" class="form-control" rows="5" id="pinglun" placeholder="请输入评论"></textarea> <input type="hidden" name="fa_id" value="{{ fa.id }}"> </div> <button type="submit" class="btn btn-default">发送</button> <br> <br> <h4>评论:({{ fa.comments|length }})</h4> <ul class="list-unstyled"> {% for foo in fa.comments %} <li class="list-group-item"> <a href="{{ url_for(‘yonghu‘,username_id=foo.author_id,tag=1) }}"><span class="glyphicon glyphicon-fire"></span>{{ foo.author.username }}</a> <span class="badge pull-right">{{ foo.creat_time }}</span> <p>{{ foo.detail }}</p> <br> </li> {% endfor %} </ul> </form> <br> <br> <br> </div> <div class="col-md-4 column "></div> {% endblock %}
这个是问答的评论页面
{% extends "daohang.html" %} {% block yonghufathertitle %}个人中心{% endblock %} {% block yonghufatherhead %} <style> .nav1 li{ padding: 10px; } </style> {% endblock %} {% block daohangbody %} <div class="col-md-4 column "></div> <div class="col-md-4 column "> <h3 class="glyphicon glyphicon-fire" href="#">{{ username }}</h3> <hr> <ul class="nav nav-pills"> <li class="active" role="presentation"><a href="{{ url_for(‘yonghu‘,username_id=userid,tag=1) }}">个人信息</a></li> <li class="active" role="presentation"><a href="{{ url_for(‘yonghu‘,username_id=userid,tag=2) }}">发布信息</a></li> <li class="active" role="presentation"><a href="{{ url_for(‘yonghu‘,username_id=userid,tag=3) }}">评论信息</a></li> </ul> {% block yonghubody %}{% endblock %} </div> <div class="col-md-4 column "></div> {% endblock %}
这个是用户中心,其中有对应用户基本信息,发布问答,评论的链接。
{% extends ‘yonghucenter.html‘ %} {% block yonghubody %} <h3 class="text-center">个人信息</h3> <ul class="list-unstyled nav1"> <li class="list-group-item-success">用户:{{ username }}</li> <li class="list-group-item-info">编号:{{ userid }}</li> <li class="list-group-item-success">问答:{{ fabus|length }}篇</li> <li class="list-group-item-info">评论:{{ comments|length }}条</li> </ul> {% endblock %}
这个是用户的基本信息页面
{% extends ‘yonghucenter.html‘ %} {% block yonghubody %} <div> <h3 class="text-center">全部发布信息({{ fabus|length }})</h3> <ul class="list-unstyled"> {% for foo in fabus %} <li class="list-group-item"> <a href="{{ url_for(‘yonghu‘,username_id=foo.author_id,tag=1) }}"><span class="glyphicon glyphicon-fire"></span>{{ foo.author.username }}</a> <h4 class="text-center"><a href="{{ url_for(‘fabuview‘,fabu_id=foo.id) }}">{{ foo.title }}</a> </h4> <span class="badge pull-right">{{ foo.creat_time }}</span> <br> <p>{{ foo.detail }}</p> </li> {% endfor %} </ul> <br> <br> <br> </div> {% endblock %}
这个是用户发布的所有评论页面
{% extends ‘yonghucenter.html‘ %} {% block yonghubody %} <div> <h3 class="text-center">全部评论信息({{ comments|length }})</h3> <ul class="list-unstyled"> {% for foo in comments %} <li class="list-group-item"> <a href="{{ url_for(‘yonghu‘,username_id=foo.author_id,tag=1) }}"><span class="glyphicon glyphicon-fire"></span>{{ foo.author.username }}</a> <span class="badge pull-right">{{ foo.creat_time }}</span> <p>{{ foo.detail }}</p> <br> </li> {% endfor %} </ul> <br> <br> <br> </div> {% endblock %}
这个是用户的全部评论页面
以上是本次作业的全部内容,可能有些说的不够详尽,但是这种实践型的作业是可以通过尝试来理解的。加油