个人心得
在这个学期,我们初接触python,python是一种面向对象的解释型计算机程序设计语言,从简单的输出输入计算,到引入 turtle库,绘制多种多样的图形包括我们的国旗,接着学习了字符串基本操作,学会了凯撒密码,自制了九九乘法表,进行了中英文词频统计,直到最后我们学习了Python+Flask+MysqL的web建设,做出了自己的网页。我们由浅入深,一步一步的学习python语言,也一点一点看见他的魅力。
在我看来python最大的特点就是其简单,容易上手.现在说说学完后的对这门语言的感觉。Python不用编译,程序在运行的过程中,由对应的解释器向CPU进行翻译,个人理解就是一边编译一边执行。而JAVA这一类语言是需要预先编译的。并且python也没用类型,也就是说一个变量即可能是int型,但是也可能是String型,而且可以随时变化。
Python对于代码格式要求也相当严格,通过对于缩进的距离来判断代码是否处于同一个代码块,这样做的好处在于代码编写看上去很统一 。Python也不依靠分号来决定一句代码是否结束,一行代码就是一句代码。且python中双引号和单引号作用一样。python语法特别简单,每行结尾不需要;语句块完全依靠层次来区别,也就是说如果本该缩进一致的地方没有对齐,则程序会报错,这就从另一个角度确保了程序的编写规范性。
关于web的建设,前端页面我们做了导肮页面、登录注册页面、发布问答页面,在后端建设过程中我们引入了flask库中的Flask, render_template,用于创建一个Flask对象以及页面的跳转,引入flask_sqlalchemy库进行数据库的关联映射等,在后端设计过程我们学了对数据的增删改查等操作,利用对数据库的查询添加功能实现了页面的登陆、注册以及发布功能,这些功能的实现根据前端页面的name属性名,后台请求接收同名name的值,再将接收的值做一系列增删查改操作。在对这些name属性命名时要注意前后端对应且同一页面不能出现相同名,否则会出现数据传递出错,在做发布详情中我们在页面跳转请求时带上需要用到的‘id’,利用该‘id’去后台查询数据,在做用户详情时我们用三个页面跳转同一个请求,不同的是在请求中用if语句判断,判断各自实现的功能并跳转不同页面。在这些过程中,其实遇到过很多的问题,css总是无法调整成自己想要的样子,就查阅参考了很多网页,模仿他们的div构造。并且在实行增删改查功能时也会出现name属性名不一致而导致功能无法实现的问题。还有在写代码时总是缺少思维,不知道该如何构建框架如何实现自己想要的功能。好在在老师和同学的帮助下还是圆满完成了这次的课题。让我感受到了自己完成一个web建设的成就感。
1.登陆用url_for加载静态文件
1.<script src="{{ url_for(‘static‘,filename=‘js/login.js‘) }}"></script>
2.flask 从static文件夹开始寻找
3.可用于加载css, js, image文件
2.继承和扩展
1.把一些公共的代码放在父模板中,避免每个模板写同样的内容。base.html
2.子模板继承父模板
1.{% extends ‘base.html’ %}
3.父模板提前定义好子模板可以实现一些自己需求的位置及名称。block
1.<title>{% block title %}{% endblock %}-MIS问答平台</title>
2.{% block head %}{% endblock %}
3.{% block main %}{% endblock %}
4.子模板中写代码实现自己的需求。block
1.{% block title %}登录{% endblock %}
2.登录界面
1.@app.route设置methods
2.GET
3.POST
1.读取表单数据
2.查询数据库
1.用户名密码对:
1.记住用户名
2.跳转到首页
1.用户名密码不对:
1.提示相应错误。
@app.route(‘/login/‘,methods=[‘GET‘,‘POST‘])
def login():
if request.method == "GET":
return render_template("login.html")
else:
username = request.form.get("username")
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
sessionpermanent = True
return redirect(url_for(‘homepage‘))
else:
return ‘password error‘
else:
return ‘username is not existed‘
js
function fnLogin() { var uname = document.getElementById("name") var uError = document.getElementById("error_box") var upassword = document.getElementById("password") var upasswordagain = document.getElementById("passwordagain") var isError =true; uError.innerHTML="<br>" if(uname.value.length<6 || uname.value.length >20){ uError.innerHTML="用户名应为6到20字符"; isError = false; return isError; }else if ((uname.value.charCodeAt(0)>=48) && (uname.value.charCodeAt(0)<=57)){ uError.innerHTML="第一位只能是字母"; isError = false; return isError; } if(upassword.value.length<6 || upassword.value.length>12){ uError.innerHTML="密码应为6到20字符"; isError = false; return isError; } return isError; window.alert("登录成功") }
3.注册界面
- js文件: onclick函数return True时才提交表单,return False时不提交表单。
- html文件:
- <form>中设置 action和method="post"
- <input> 中设置 name
- 主py文件中:
- from flask import request, redirect, url_for
- @app.route(‘/regist/‘, methods=[‘GET‘, ‘POST’])
@app.route("/register/",methods=[‘GET‘,‘POST‘])
def register():
if request.method == "GET":
return render_template("register.html")
else:
username = request.form.get("username")
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‘))
js
function fnLogin() { var uname = document.getElementById("name") var uError = document.getElementById("error_box") var upassword = document.getElementById("password") var upasswordagain = document.getElementById("passwordagain") var isError =true; if(uname.value.length<6 || uname.value.length >20){ uError.innerHTML="用户名应为6到20字符"; isError = false; return isError; }else if ((uname.value.charCodeAt(0)>=48) && (uname.value.charCodeAt(0)<=57)){ uError.innerHTML="第一位只能是字母"; isError = false; return isError; } else for (var i=0 ; i<uname.value.length;i++){ if (uname.value.charCodeAt(i)<48 || (uname.value.charCodeAt(i)>57)&&(uname.value.charCodeAt(i)<97)|| uname.value.charCodeAt(i)>122){ uError.innerHTML="用户名只能为数字或者字母"; isError = false; return isError; } } if(upassword.value.length<6 || upassword.value.length>12){ uError.innerHTML="密码应为6到20字符"; isError = false; return isError; } if (upasswordagain.value!=upassword.value ) { uError.innerHTML = "重新输入你的密码"; isError = false; return isError; } return isError; window.alert("注册成功") }
3.发布问答界面
1.编写要求登录的装饰器
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.完成发布函数。
保存到数据库。
重定向到首页
@app.route(‘/question/‘, methods=[‘GET‘ , ‘POST‘])
@log
def question():
if request.method == ‘GET‘:
return render_template(‘question.html‘)
else:
question = request.form.get(‘question‘)
questionDetail = request.form.get(‘questionDetail‘)
author_id = User.query.filter(User.username == session.get(‘user‘)).first().id
question = Question(question = question, questionDetail = questionDetail, author_id = author_id)
db.session.add(question)
db.session.commit()
return redirect(url_for(‘homepage‘))
4.发布评论
1.定义评论的视图函数
@app.route(‘/comment/‘,methods=[‘POST‘])
def comment():
读取前端页面数据,保存到数据库中
@app.route(‘/comment/‘,methods=[‘GET‘,‘POST‘]) @loginFirst def comment(): if request.method == ‘GET‘: return render_template(‘question_detail.html‘) else: detail = request.form.get(‘detail‘) author_id =User.query.filter(User.username == session.get(‘user‘)).first().id question_id=request.form.get(‘question_id‘) comments = Comment(detail=detail,author_id=author_id,question_id=question_id) db.session.add(comments) db.session.commit() return redirect(url_for(‘question_detail‘,question_id=question_id))
2.用<input type="hidden" 方法获取前端的"question_id"
3.显示评论次数
4.要求评论前登录
{% extends ‘index.html‘ %} {% block title %}问答详情{% endblock %} {% block main %} <body style="url(../image/picture.jpg) no-repeat" > <div class="container"> <div> <h2>{{ ques.question }}<br><small>{{ ques.author.username }} <span class="badge">{{ ques.creat_time }}</span></small></h2></div> 问题详情:<p class="lead">{{ ques.questionDetail }}</p> <p class="location">评论</p> <hr> <form action="{{ url_for(‘comment‘) }}" method="post"> <div class="form-group"> <textarea name="new_comment" class="form-control" id="new_comment" rows="3" placeholder="write your comment"style="height:200px;width:800px" ></textarea><br> <input name="question_id" type="hidden" value="{{ ques.id }}"/> </div> <button type="submit" class="fabu"style="width:100px">发布</button> </form> <h4>评论:({{ ques.comments|length }})</h4> </div> <ul class="list-group"style="width:700px;height:auto;border-style:groove;"> {% for b in ques.comments %} <li class="list-group-item"style="list-style: none"> <span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span> <a href="#">{{ b.author.username }}</a> <span class="badge">{{b.creat_time}}</span> <p style="">{{b.detail}}</p> </li> {% endfor %} </ul> </body> {% endblock %}
5.首页
1. 在首页添加显示问答的列表,并定义好相应的样式。
无序列表
<ul >
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
2. 用字典向index.html传递参数。
- 首页列表显示全部问答:
- 将数据库查询结果传递到前端页面 Question.query.all()
- 前端页面循环显示整个列表。
- 问答排序
- 完成问答详情页布局:
- 包含问答的全部信息
- 评论区
- 以往评论列表显示区。
- 在首页点击问答标题,链接到相应详情页。
- 主PY文件写视图函数,带id参数。
@app.route(‘/detail/<question_id>‘)
def detail(question_id):
quest =
return render_template(‘detail.html‘, ques = quest) - 首页标题的标签做带参数的链接。
{{ url_for(‘detail‘,question_id = foo.id) }} - 在详情页将数据的显示在恰当的位置。
{{ ques.title}}
{{ ques.id }}{{ ques.creat_time }}{{ ques.author.username }}
{{ ques.detail }} -
建立评论的对象关系映射:
class Comment(db.Model):
__tablename__=‘comment‘{% extends‘index.html‘ %} {% block title %} 主页 {% endblock %} {% block head %} <link href="{{ url_for(‘static‘,filename=‘CSS/homepage.css‘) }}" rel="stylesheet" type="text/css"> {% endblock %} {% block main %} <div style="margin:80px"> {% for a in question %} <div note-list style="margin:0 auto;width:1000px;height:auto;border-style:groove;"> <ul class="list-group" style="list-style: none;"> <li class="list-group-item,"> <span class="glyphicon glyphicon-leaf" aria-hidden="true"></span> <a href="{{ url_for(‘detail‘,question_id=a.id) }}"> {{ a.question }}</a><br><br> <a href="{{ url_for(‘personal‘,user_id=a.author.id,tag=1) }}">{{ a.author.username }}</a> <span class="badge">{{ a.creat_time }}</span> <p style="text-indent: 18px">{{ a.questionDetail }}</p> <h4>评论:({{ a.comments|length}})</h4> </li> </ul></div> {% endfor %} {% endblock %}
@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)
6.个人中心
- 个人中心—视图函数带标签页面参数tag
- @app.route(‘/usercenter/<user_id>/<tag>‘)
def usercenter(user_id, tag):
if tag == ‘1‘:
return render_template(‘usercenter1.html‘, **context)@app.route(‘/personal/<user_id><tag>‘) @log def personal(user_id,tag): user=User.query.filter(User.id==user_id).first() mycontext={ ‘user‘:user, ‘questions‘: user.question, ‘comments‘: user.comments, } if tag ==‘1‘: return render_template(‘user1.html‘,**mycontext) elif tag ==‘2‘: return render_template(‘user2.html‘,**mycontext) else: return render_template(‘user3.html‘,**mycontext) @app.route(‘/ModifyPassword/‘,methods=[‘GET‘,‘POST‘])
3.个人中心—导航标签链接增加tag参数
<li role=“presentation”><a href=“{{ url_for(‘usercenter’,user_id = user.id,tag = ‘1’) }}">全部问答</a></li>
<li role="presentation"><a href="{{ url_for(‘self‘,user_id=user.id,tag=‘1‘) }}">全部问答</a> </li> <li role="presentation"><a href="{{ url_for(‘self‘,user_id=user.id,tag=‘2‘) }}">全部评论</a> </li> <li role="presentation"><a href="{{ url_for(‘self‘,user_id=user.id,tag=‘3‘) }}">个人信息</a> </li>
4.个人中心—有链接到个人中心页面的url增加tag参数
<a href="{{ url_for(‘usercenter‘,user_id = session.get(‘userid‘), tag=1) }}">{{ session.get(‘user‘) }}</a>
7.实现导航条中的搜索功能
1.修改base.html 中搜索输入框所在的
- <form action="{{ url_for(‘search‘) }}" method="get">
- <input name="q" type="text" placeholder="请输入关键字">
2.完成视图函数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)
@app.route(‘/search/‘) def search(): qu=request.args.get(‘q‘) ques=Question.query.filter( or_( Question.title.contains(qu), Question.detail.contains(qu) ) ).order_by(‘-creatTime‘) return render_template(‘index.html‘,question=ques)
7.夜间模式
function mySwitch(){
var uBody=document.getElementById("myBody");
var Onoff=document.getElementById("myOnOff");
if(Onoff.src.match("bulbon")){
Onoff.src="https://www.runoob.com/images/pic_bulboff.gif";
uBody.style.background="black";
uBody.style.color="white";
}else{
Onoff.src="https://www.runoob.com/images/pic_bulbon.gif";
uBody.style.background="white";
uBody.style.color="black";
}
}