期末作品检查
- 个人学期总结
- 总结Python+Flask+MysqL的web建设技术过程,标准如下:
- 即是对自己所学知识的梳理
- 也可作为初学入门者的简单教程
- 也可作为自己以后复习的向导、
- 也是一种向外展示能力的途径
通过一个学期的学习,从从未听过的工具到现在的能完整的做出一个属于个人的网站,这其中不得不说的是有很大的进步。一开始接触Python学习的时候,第一个感觉是有点比较简单、易上手。因为博主之前学过Java语言,也用Java做过一些小程序,就同一个程序来说,Python真的要简单很多了,对于刚学程序的小白来说,挺好的。但是在大的项目上,Java能运用的功能会更强大一些。博主只是前期学习了一下Python,在后面的大作业中,做出的网页是用了Python+Flask做页面的设计及调整,数据的存储是用了MySQL。下面就给大家介绍一下我做页面的工作,希望对刚学习做网页的人有所帮助。当然,我能力有限,网页实现的功能就比较简单,就只有简单的登录、注册、发布、评论、站内搜索、个人中心几个功能,修改密码、上传图片等功能博主还没弄出来,弄出来了再跟大家分享。新人教学,请勿喷!
首先,我们来认识一下我们做网页需要用到的工具,分别是:pycharm和navicat for MySQL ,如下图所示,对,就是这两个小调皮
安装完之后,我们要先配置一下pycharm的环境,首先先创建一个数据库,在MySQL里创建也可以,或者直接打开doc命令符直接创建,创建数据库的话,个人比较习惯用doc命令符做,不多说,直接上图演示
进入之后输入mysql -u root -p,若有密码就输入密码,若无,就直接按enter键,出现一堆没有红色的字体就成功的进入数据库了。下图
建数据库之前,我们先看一下数据库中有没有我们想建的数据库的名字,执行show databases命令就可以看到MySQL中所有的数据库了,然后就可以创建了
创建完成后再看一下数据库,存在了,OK!
数据库的配置我们就完成了,接下来的工作就交给Python跟flask了
注意:flask项目是建立在python之上的,没有下载安装python的同学是运行不了flask项目的!
(1)打开pycharm,创建一个flask项目
(2)创建完flask项目之后,在static文件之下创建三个文件夹,分别拿来存放css文件、js文件以及网页设计会用到的图片,在templates文件下专门放HTML文件,再创建一个config文件。
(3)先用HTML文件中的div跟form表单做出一个登录页面(注册页面同)
<div id="container" style="width:400px;margin:0px auto;" > <div id="header" style="background-color:hotpink"><h2 align="center" style="margin-bottom: 0;">粉丝登录</h2></div> <div id="content" style="background-color:pink;height:150px;width:400px;float:left;text-align:center;line-height:40px;"> <from> username:<input type="text"name="用户名"placeholder="请输入昵称:"><br> password:<input type="password"neme="密码"placeholder="请输入密码:"><br> <input type="radio"name="choose">粉丝 <input type="radio"name="choose1">路人 <input type="radio"name="choose2">黑粉<br> <input type="button"value="login"style="margin-right:10px;font-size:15px;"> <input type="button"value="cancel"style="font-size:15px"> </from> </div> </div><br>
(4)一个网页少不了的就是导航条了
头部导航
<nav> <img src="https://p1.ssl.qhmsg.com/dr/220__/t015512ddbe7e900f7f.jpg"><br> <a href="">首页</a> <a href="">下载</a> <input type="text"name="search"> <button type="submit">搜索</button> <a href="">登录</a> <a href="">注册</a> </nav>
底部导航
<div class="box"> <a href="" class="nav"><span>关于我们</span></a> <a href="" class="nav"><span>意见反馈</span></a> <a href="" class="nav"><span>安全保障</span></a> </div>
(5)我们经常看见网站到了晚上的时候总是会有护眼或者夜间模式,我们也尝试做一下,用一张图片作为我们的按钮,控制网页是夜间还是白天模式
<img id="on_off" onclick="change()#定义的开灯关灯的方法" src="{{ url_for("static",filename="images/on.jpg") }}" #图片的地址 width="30px"></form>
弄好以上之后,我们大概的简易的网页就出来了,然后就是怎么去实现我们页面上的一些功能了。
(1)先是登录的功能实现,这里我们要用到<script></script>来调用方法,有三种用法,看个人喜欢,我是习惯把<script></script>放在js文件里(上面有让大家创建过了),或者直接放在body里面也没关系。写完了方法记得在登录的页面上调用哦,用oneclick函数。
function myLogin#定义一个登录的方法() { var uName = document.getElementById("username");#用获取标签id的方法得到标签的值 var uError = document.getElementById("error_box"); var uPass =document.getElementById("userpass"); 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; } 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 (uPass.value.length<6||uPass.value.length>20){ uError.innerHTML="密码为6-20位!"; isError = false; return isError; } return isError; }
上面的是登录的界面,注册的页面更上面很像,一样是做出页面,写出方法,调用方法。可以参考登录页面啦。
(2)白天与夜间模式方法
function change(){ var chan=document.getElementById("on_off"); if(chan.src.match("on")){ chan.src="../static/images/off.png"; document.getElementById("myBody").style.background="gray"; document.getElementById("myBody").style.color="white" }else{ chan.src="../static/images/on.jpg"; document.getElementById("myBody").style.background="white"; document.getElementById("myBody").style.color="gray" } }#也是放在js文件中的
(3)方法可以了,但是页面为什么还跳转不了呢?别着急,马上就介绍。我们需要使用装饰器,设置路径与函数之间的关系,使用flask中的render_template,用不同的路径返回首页、登录页、注册页;用视图函数反转得到URL,完成导航条里的链接。
from flask import Flask,render_template app = Flask(__name__) @app.route('/')#定义首页的路径 def vi(): return render_template("vi.html") @app.route("/login")#定义登录页的路径 def login(): return render_template("vv.html") @app.route("/regiter")#定义注册页的路径 def regiter(): return render_template("vv1.html") if __name__ == '__main__': app.run(debug=True)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="../static/vv.css" rel="stylesheet" type="text/css">#在外部调用方法一定要加上方法文件的路径,不然获取不到 <script src="../static/change.js"></script> <nav class="nav"> <a href="{{ url_for("vi")}}">首页</a>#反转函数连接到首页页面,下同 <a href="">下载</a> <input type="text"name="search"> <button type="submit">搜索</button> <a href="{{ url_for("login")}}">登录</a> <a href="{{ url_for("regiter")}}">注册</a> </nav>#头部导航条 </head> <body id="myBody"> <img id="on_off" onclick="change()" src="../static/images/on.jpg" width="50px">#开灯关灯 <div class="box"> <a href="" class="nav"><span>关于我们</span></a> <a href="" class="nav"><span>意见反馈</span></a> <a href="" class="nav"><span>安全保障</span></a> </div>#底部导航条 </body> </html>
(4)页面可以跳转了,但是导航条只有首页才有,跳到下一个页面就没有了,怎么办呢?我们可以采用继承的方法去解决。首先把你想要被继承的东西放到一个名为base.html的文件中,在父模板中提前定义好子模板可以实现一些自己需求的位置及名称,在子模板中写继承与语言可以了。
父模板 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %}{% endblock %}Victoria</title> <link href="../static/css/vv.css" rel="stylesheet" type="text/css"> <script src="{{url_for("static",filename="js/change.js")}}"> </script> {% block head %}{% endblock %}#定义head的位置 </head> <body id="myBody"> <nav class="nav"> <a href="{{ url_for("vi")}}">首页</a> <a href="">下载</a> <input type="text" name="search"> <button type="submit">搜索</button> <a href="{{ url_for("login")}}">登录</a> <a href="{{ url_for("regist")}}">注册</a> <img id="on_off" onclick="change()" src="{{ url_for("static",filename="images/on.jpg") }}" width="30px"> </nav> {% block main %}{% endblock %} <div class="box"> <a href="" class="nav"><span>关于我们</span></a> <a href="" class="nav"><span>意见反馈</span></a> <a href="" class="nav"><span>安全保障</span></a> </div> </body> </html>
{% extends 'base.html' %}#继承父模板 {% block title %} 登录 {% endblock %} {% block head %} <link href="{{ url_for("static",filename="css/vv.css") }}" rel="stylesheet" type="text/css"> <script src="{{ url_for("static",filename="js/new.js") }}"></script> {% endblock %} {% block main %} <body bgcolor="#778899" class="div4"> <div class="div1"> <h2 class="title"></h2> <div class="normal-title"> <a class="div2" href="{{ url_for("templates",filename="vv.html") }}">登录</a> <b>|</b> <a class="div2" href="{{ url_for("templates",filename="vv1.html") }}">注册</a> </div> <div class="div3"> 用户:<input id="username" type="text" placeholder="请输入昵称"> </div> <div class="div3"> 密码:<input id="userpass" type="text" placeholder="请输入密码"> </div> <div id="error_box"><br></div> <div class="div3"> <button onclick="myLogin()">Login</button> </div> <div class="div2">ByYin</div> </div> <br> </body> {% endblock %} </html>
(5)弄完以上,我们接下来就可以做把数据从页面中直接存储到数据库中去的工作了。
下载安装MySQL数据库(安装过就不用了),下载安装MySQL-python 中间件,然后pip install flask-sqlalchemy (Python的ORM框架SQLAlchemy)
在config.py文件里写下这些代码
import os SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root#端口名:#数据库密码 @127.0.0.1#IP:3306#端口号/chu#数据库名字?charset=utf8' SQLALCHEMY_TRACK_MODIFICATIONS = False
SECRET_KEY = os.urandom(24)
(6)在doc命令符中创建数据库,数据库下有三张表,一张用户表:用来存登录、注册页面所需数据;一张发布问题表:用来存储用户发布问题的数据;最后一张表是评论表:用来存对已发布的问题进行评论的评论数据。
class User(db.Model): __tablename__ = "user" id = db.Column(db.Integer,primary_key=True,autoincrement=True) username = db.Column(db.String(20),nullable=False) _password = db.Column(db.String(200),nullable=False) nickname = db.Column(db.String(20)) @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) create_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) detail = db.Column(db.Text, nullable=False) create_time = db.Column(db.DateTime, default=datetime.now) author_id = db.Column(db.Integer, db.ForeignKey("user.id")) question_id=db.Column(db.Integer,db.ForeignKey("question.id")) author = db.relationship("User", backref=db.backref('comment')) question = db.relationship("Question",backref=db.backref("comment",order_by=create_time.desc)) #db.create_all() #第一次创建记得帮这里的注释符去掉,不然没有表
(7)完成登录功能
session:
- 从`flask`中导入`session`
- 设置`SECRET_KEY`
- 操作字典一样操作`session`:增加用户名`session['username']=`username
from flask import Flask,render_template,request,redirect,url_for,session 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=True,autoincrement=True) username = db.Column(db.String(20),nullable=False) password = db.Column(db.String(20),nullable=False) nickname = db.Column(db.String(20)) #db.create_all() @app.route('/') def vi(): return render_template("base.html") @app.route('/first') def base(): return render_template("base.html") @app.route("/login",methods=["GET","POST"]) def login(): if request.method == "GET": return render_template("login.html") else: usern = request.form.get("usern") passw = request.form.get("userp") user = User.query.filter(User.username==usern).first() if user: if user.password == passw: session["user"] = usern # session.permanent = True return redirect(url_for("base")) else: return "密码错误,请重新输入!" else: return "用户名不存在!" @app.route("/regist",methods=["GET","POST"]) def regist(): if request.method == "GET": return render_template("regist.html") else: usern1 = request.form.get("newn") passw1 = request.form.get("newp") user = User.query.filter(User.username==usern1).first() if user: return "用户名已存在!" else: user = User(username = usern1,password = passw1) db.session.add(user) db.session.commit() return redirect(url_for("login")) if __name__ == '__main__': app.run(debug=True)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %}{% endblock %}宋茜后援团</title> <link href="../static/css/vv.css" rel="stylesheet" type="text/css"> <script src="{{url_for("static",filename="js/change.js")}}"> </script> {% block head %}{% endblock %} </head> <body id="myBody"> <nav class="nav"> <a href="{{ url_for("first")}}">首页</a> <a href="">下载</a> <input type="text" name="search"> <button type="submit">搜索</button> {% if username %} <a href="#">{{ username }}</a> <a href="{{ url_for('clear') }}">注销</a> {% else %} <a href="{{ url_for("login")}}">登录</a> <a href="{{ url_for("regist")}}">注册</a> {% endif %} <img id="on_off" onclick="change()" src="{{ url_for("static",filename="images/on.jpg") }}" width="30px"> </nav> {% block main %}{% endblock %} <div class="box"> <a href="" class="nav"><span>关于我们</span></a> <a href="" class="nav"><span>意见反馈</span></a> <a href="" class="nav"><span>安全保障</span></a> </div> </body> </html
(9)完成了登录注册功能后,我们还增加了一项发布问答的功能。
@app.route('/') def vi(): return render_template("base.html") @app.route('/first') def first(): return render_template("first.html") def login_first(func): @wraps(func) def wrapper(*args,**kwargs): if session.get('user'): return func(*args,**kwargs) else: return redirect(url_for('login'))#要先登录才能在页面进行操作 return wrapper @app.route('/question',methods=["GET","POST"]) @login_first def question(): if request.method == 'GET': return render_template('question.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('first')) @app.route("/login",methods=["GET","POST"]) def login(): if request.method == "GET": return render_template("login.html") else: usern = request.form.get("usern") passw = request.form.get("userp") user = User.query.filter(User.username==usern).first() if user: if user.password == passw: session["user"] = usern # session.permanent = True return redirect(url_for("first")) else: return "密码错误,请重新输入!" else: return "用户名不存在!" @app.route("/regist",methods=["GET","POST"]) def regist(): if request.method == "GET": return render_template("regist.html") else: usern1 = request.form.get("newn") passw1 = request.form.get("newp") user = User.query.filter(User.username==usern1).first() if user: return "用户名已存在!" else: user = User(username = usern1,password = passw1) db.session.add(user) db.session.commit() return redirect(url_for("login")) @app.context_processor def context(): usern=session.get("user") if usern: return{'username':usern} else: return {} @app.route('/clear') def clear(): session.clear() return redirect(url_for('first'))#注销
{% extends 'base.html' %} {% block title %} 问题发布 {% endblock %} {% block head %} <link rel="stylesheet" href="{{ url_for('static',filename='css/vv.css')}}" type="text/css"> {% endblock %} {% block main %} <form action="{{ url_for("question") }}" method="post"> <div id="container"> <div id="header" ><h3 align="center" style="margin-bottom:0;font-size: 33px;font-family: 楷体" >问答平台</h3></div> <div id="content" > <label for="wen" >问答</label><br> <textarea style="width: 400px" id="wen" name="title"></textarea><br> <label for="xiang" >详情</label><br> <textarea style="width: 400px" id="xiang"rows="10" name="detail"></textarea><br> <input type="submit" value="提交"style="width:65px;height:25px;font-size:15px"> </div> </div> </form>> {% endblock %}
(10)发布玩问答后,我们还可以对别人发布的文章、问题进行评论。
@app.route('/detail') def detail(): return render_template("detail.html") @app.route('/first') def first(): context={ "question":Question.query.all() } return render_template("first.html",**context)
{% extends 'base.html' %} {% block title %} 首页 {% endblock %} {% block head %} <link href="../static/css/first.css" rel="stylesheet" type="text/css"> <script src="{{url_for("static",filename="js/change.js")}}"> </script> {% endblock %} {% block main %} <body id="myBody"> {% for foo in question %} <div id="list-container"> <ul class="note"> <li> <div class="content"> <div class="author"> <a class="nickname" target="_blank" href="{{ url_for("detail") }}">{{ foo.author.username }}</a> <span class="time">{{ foo.create_time }}</span> </div> </div> <a class="title" target="_blank" href="{{ url_for("detail") }}">标题:{{ foo.title }}</a> <p class="abstract">详情:{{ foo.detail }}</p> </li> </ul> </div> {% endfor %} <div class="box"> <a href="" class="nav"><span>关于我们</span></a> <a href="" class="nav"><span>意见反馈</span></a> <a href="" class="nav"><span>安全保障</span></a> </div> {% endblock %}
{% extends "base.html" %} {% block title%}问答详情{% endblock %} {% block main %} <body bgcolor="#696969"> <div class=""> <a href="#">username</a><br> <a class="" href="#">title</a><br> <span class="createtime">create_time</span> <p class="location">评论</p> <textarea style="width: 400px" id="xiang" rows="10" name="detail"></textarea><br> <input type="submit" value="发送"style="width:65px;height:25px;font-size:15px"> </div> </body> {% endblock %}
(11)从首页进入到详情页
@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)
<body id="myBody"> {% for foo in question %} <div id="list-container"> <ul class="note"> <li> <div class="content"> <div class="author"> <a class="nickname" target="_blank" href="{{ url_for("detail",question_id=foo.id) }}">{{ foo.author.username }}</a> <span class="time">{{ foo.create_time }}</span> </div> </div> <a class="title" target="_blank" href="{{ url_for("detail",question_id=foo.id) }}">标题:{{ foo.title }}</a> <p class="abstract">详情:{{ foo.detail }}</p> </li> </ul> </div> {% endfor %}
<body bgcolor="#696969"> <div class=""> <small>{{ ques.author.username }}</small><br> <h3>{{ ques.title }}</h3><br> <span class="createtime">{{ ques.create_time }}</span> <p>{{ ques.detail }}</p> <form action="{{ url_for("comment") }}" method="post"> <p class="location">评论</p> <textarea style="width: 400px" id="xiang" rows="10" name="detail1"></textarea><br> <input type="submit" value="发送" style="width:65px;height:25px;font-size:15px"> </form> </div> </body>
(12)完成评论功能并保存到数据库当中,获取评论数量,并显示出来
@app.route('/comments',methods=["POST"]) @login_first def comments(): comment = request.form.get("detail1") author_id = Question.query.filter(User.username == session.get('user')).first().id ques_id = request.form.get("question_id") comm = Comment(detail=comment, author_id=author_id,question_id=ques_id) db.session.add(comm) db.session.commit() return redirect(url_for('detail',question_id=ques_id))
<form action="{{ url_for("comments") }}" method="post"> <div> <textarea style="width: 400px" id="xiang" rows="5" name="detail1" placeholder="请输入您的评论"></textarea><br> <input style="display: none" value="{{ ques.id }}" name="question_id"/> <input type="submit" value="发送" style="width:45px;height:25px;font-size:15px"> </div> </form> <div> <h4 >评论:({{ ques.comment|length }})</h4> <ul class="note"> {% for foo in ques.comment %} <li class="lis"> <div class="author"> <a class="nickname" target="_blank" href="{{ url_for("detail",question_id=foo.id) }}">{{ foo.author.username }}说:</a> <span class="time">{{ foo.create_time }}</span> <p>{{ foo.detail }}</p> </div> </li> {% endfor %} </ul>
(13)一般上网页都会有我的或者个人中心,以便用户查看自己的信息。
@app.route('/user_detail<user_id>') @login_first def user_detail(user_id): user=User.query.filter(User.id == user_id).first() context={ "user":user } return render_template("user.html",**context)
{% extends "base.html" %} {% block title%}用户详情{% endblock %} {% block head %} <style> .u_ul li{ float: left; margin: 20px; list-style: none; } </style> {% endblock %} {% block main %} <ul class="u_ul"> <li role="presentation"><a href="{{ url_for("user_detail",user_id = user.id)}}">全部问答</a></li> <li role="presentation"><a href="{{ url_for("user_detail",user_id = user.id)}}">全部评论</a></li> <li role="presentation"><a href="{{ url_for("user_detail",user_id = user.id)}}">个人信息</a></li> </ul> {% block user %}{% endblock %} {% endblock %}
{% extends "user.html" %} {% block user %} <form class="basic"> {% for foo in user.question %} <h2>{{ foo.username }}<span>全部问答</span></h2> <fieldset> <span >{{ foo.create_time }}</span> <h3>{{ foo.title }}</h3> <h3>{{ foo.detail}}</h3> </fieldset> {% endfor %} </form> {% endblock %}
{% extends "user.html" %} {% block user %} <form class="basic"> {% for foo in user.comment %} <h2>{{ foo.username }}<span>全部评论</span></h2> <fieldset> <span>{{ foo.create_time }}</span> <h3>{{ foo.detail}}</h3> </fieldset> {% endfor %} </form> {% endblock %}
{% extends "user.html" %} {% block user %} <form class="basic"> <fieldset> <span>个人信息</span> <ul> <li>用户:{{ user.username }}</li> <li>编号:{{ user.id }}</li> <li>文章篇数:{{ user.question|length }}</li> </ul> </fieldset> </form> {% endblock %}
(14)网页上还会有搜索功能
@app.route("/search") def search(): qu = request.args.get("q") que = Question.query.filter( or_( Question.title.contains(qu), Question.detail.contains(qu) )).order_by("-create_time") return render_template("first.html",question = que)
<form action="{{ url_for("search") }}" method="get" style="float: right"> <input name ="q" type="text" placeholder="请输入关键字"> <button type="submit">搜索</button> </form
(15)网站除了精美、实用之外,更应该注意的问题就是安全性。像我们上面说的密码都没有受保护,有心人黑进数据库里的话,用户的信息什么的就会全部暴露在外,所以我们还要学会给我们的网站加上一层保护锁。
class User(db.Model): __tablename__ = "user" id = db.Column(db.Integer,primary_key=True,autoincrement=True) username = db.Column(db.String(20),nullable=False) _password = db.Column(db.String(200),nullable=False) nickname = db.Column(db.String(20)) @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("/login",methods=["GET","POST"]) def login(): if request.method == "GET": return render_template("login.html") else: usern = request.form.get("usern") passw = request.form.get("userp") user = User.query.filter(User.username==usern).first() if user: if user.check_password(passw): session["user"] = usern session["id"] = user.id session.permanent = True return redirect(url_for("first")) else: return "密码错误,请重新输入!" else: return "用户名不存在!"
要注意如果一开始不是上锁的话,就要重新创建一下表,不然会出错。
好啦,以上就是我本学期学习的一些网站内容,不足之处有很多,希望在以后的网页设计上能够有更大的进步,能够做出完完全全属于自己的网站,希望我写的东西对大家,哪怕一个人有用,都行,谢谢大家能看到最后,感恩!!!以上有不足的地方,欢迎大家指正!!!