Python+Flask+MysqL的web建设技术过程
一、前言(个人学期总结)
个人总结一下这学期对于Python+Flask+MysqL的web建设技术过程的学习体会,Flask小辣椒框架相对于其他框架而言,更加稳定,不会有莫名其妙的错误,容错性强,运行效果好,报错信息明了, Python是近几年流行起来的语言,简单易懂,很好上手,强大的库让我们可以站在巨人的肩膀上写代码,应证了人们常说的那句“人生苦短,我用python”,MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,基本功能都能准确无误的给予数据支持。在本次建站过程中,前端界面采用的是html、css、JavaScript,后端采用python作为支持。
从一开始接触的是turtle库绘制图形,在没有接触基本语法的情况下,以为会因为基础不扎实而学起来吃力,然而,turtle库的学习,打开了我们对python的学习兴趣的闸门,这是一门多么简洁实用的语言,python的第三方库是多么的强大,逐渐的,在对库的使用中熟悉了python的语法,学起来一点也不吃力,有了html基础,加上Bootstrap框架的引用,就可以制作出一个静态页面,再有了python基础以及连接数据库的知识,就可以完成web建站了。
本次的mysql运用的是远程数据库,便于搭建环境和数据存储,可视化软件是SQLyog。
二、使用工具
主要工具有:pycharm64.exe + Python 3.6 64-bit + MySQL +SQLyog(辅助工具)
Python下载地址:https://www.python.org/downloads/
MySQL下载地址:https://www.mysql.com/downloads/
Pycharm下载地址:https://www.jetbrains.com/pycharm/download/#section=windows
三、完成基本的页面设计
①导航条
②登陆界面
③注册界面
④发布问答界面
四、Flask & 概览
1、初始化
在这章,你将学到Flask应用程序的不同部分。同时,你将编写和运行你的第一个Flask web应用程序。
所有的Flask应用程序都必须创建一个 应用程序实例 。使用web服务器网关接口协议将所有从客户端接收的请求传递给这个对象处理。这个应用程序实例就是Flask类的一个对象,通常使用下面的方式创建:
1
2
|
from flask import Flask app = Flask(__name__) |
Flask类构造函数唯一需要的参数就是应用程序的主模块或包。对于大多数应用程序,Python的__name__变量就是那个正确的、你需要传递的值。
注:对于Flask开发者来说,传给Flask应用程序构造函数的name参数是比较容易弄混淆的。Flask使用这个参数来确定应用程序的根目录,这样以后可以相对这个路径来找到资源文件。
稍后你可以看到更复杂的应用程序实例初始化,但是对于简单应用程序这些已经足够了。
2、路由和视图函数
客户端例如web浏览器发送 请求 给web服务,进而将它们发送给Flask应用程序实例。应用程序实例需要知道对于各个URL请求需要运行哪些代码,所以它给Python函数建立了一个URLs映射。这些在URL和函数之间建立联系的操作被称之为 路由 。
在Flask应程序中定义路由的最便捷的方式是通过显示定义在应用程序实例之上的app.route装饰器,注册被装饰的函数来作为一个路由。下面的例子会演示怎样使用装饰器来申明一个路由:
1
2
3
|
@app .route( '/' ) def index(): return '<h1>Hello World!</h1>' |
注:装饰器是Python语言的标准特性;它们可以以不同方式改变函数的行为。一个常见的模式是使用装饰器来注册函数作为一个事件处理程序。
在上一个示例给应用程序的根URL注册index()函数作为事件的处理程序。如果这个应用程序被部署在服务器上并绑定了 www.example.com 域名,然后在你的浏览器地址栏中输入 http://www.example.com 将触发index()来运行服务。客户端接收到的这个函数的返回值被称为 响应 。如果客户端是web浏览器,响应则是显示给用户的文档。
类似于index()的函数被称作 视图函数 。通过视图返回的响应可以是简单的HTML内容的字符串,但它也可以市更复杂的形式,正如您将看到的。
注:响应字符串嵌入在Python代码中导致代码难以掌控,在此只是介绍响应的概念。你将在第三章学习正确的方法来生成响应。
如果你注意到你每天使用的一些网站URLs如何形成的,你将会发现很多都有变量。例如,你的Facebook个人信息页的URL是 http://www.facebook.com/<username> ,所以你的用户名是它的一部分。Flask在路由装饰器中使用特殊的语法支持这些类型的URLs。下面的示例定义了一个拥有动态名称组件的路由:
1
2
3
|
@app .route( '/user/<name>' ) def user(name): return '<h1>Hello, %s!</h1>' % name |
用尖括号括起来的部分是动态的部分,所以任何URLs匹配到静态部分都将映射到这个路由。当视图函数被调用,Flask发送动态组件作为一个参数。在前面的示例的视图函数中,这个参数是用于生成一个个性的问候作为响应。
在路由中动态组件默认为字符串,但是可以定义为其他类型。例如,路由/user/<int:id>只匹配有一个整数在id动态段的URLs。Flask路由支持int、float和path。path同样是字符串类型,但并不认为斜杠是分隔符,而认为它们是动态组件的一部分。
3、服务启动
应用程序实例有一个run方法用于启动Flask集成的web服务:
1
2
|
if __name__ = = '__main__' : app.run(debug = True ) |
__name__ == '__main__'在此处使用是用于确保web服务已经启动当脚本被立即执行。当脚本被另一个脚本导入,它被看做父脚本将启动不同的服务,所以app.run()调用会被跳过。
一旦服务启动,它将进入循环等待请求并为之服务。这个循环持续到应用程序停止,例如通过按下Ctrl-C。
有几个选项参数可以给app.run()配置web服务的操作模式。在开发期间,可以很方便的开启debug模式,将激活 debugger 和 reloader 。这样做是通过传递debug为True来实现的。
注:Flask提供的web服务并不用于生产环境。你将在十七章学习生产环境的web服务。
4、一个完整的应用程序
在上一节,你学习了Flask web应用程序的不同部分,现在是时候写一个了。整个 hello.py 应用程序脚本只不过将前面描述的三个部分结合在一个文件中。应用程序示例2-1所示。
示例 hello.py:一个完整的Flask应用程序
1
2
3
4
5
6
7
8
9
10
11
12
13
|
from flask import Flask app = Flask(__name__) @app .route( '/' ) def index(): return ' <h1>Hello World!< / h1> ' if __name__ = = '__main__' : app.run(debug = True ) |
经过这个过程,一个完整的Flask应用程序就搭建起来了。
五、加载静态文件,父模板与其他界面的继承
1.加载静态文件
- <script language="javascript" type="text/javascript" src="{{ url_for('static',filename="js/basic.js") }}"></script>
- <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename="css/basic.css") }}">
2.父模板的设置
- <!DOCTYPE>
- <html>
- <head>
- <meta charset="utf-8">
- <title>{% block title %}{% endblock %}</title>
- </head>
- <body id="myBody" style="min-width: 1500px;" background="{{ url_for('static',filename="img/timg1.jpg") }}">
- {% block aa %}{% endblock %}
- </body>
- </html>
3.子模板继承
主页:
- {% extends 'base.html' %}
- {% block title %} 主页{% endblock %}
- {% block aa %}
- {% endblock %}
注册:
- {% extends 'base.html'%}
- {% block title %} 注册{% endblock %}
- {% block aa %}
- {% endblock %}
登录:
- {% extends 'base.html' %}
- {% block title %} 登录{% endblock %}
- {% block aa %}
- <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename="css/login.css") }}">
- <script language="javascript" type="text/javascript" src="{{ url_for('static',filename="js/login.js") }}"></script>
- {% endblock %}
个人父模板:
- {% extends 'base.html' %}
- {% block title %} 个人中心{% endblock %}
- {% block aa %}
- {% block user %}{% endblock %}
- </div>
- {% endblock %}
个人子模板:
- {% extends 'user.html' %}
- {% block user %}
- {% endblock %}
问答页:
- {% extends 'base.html' %}
- {% block title %} 互动{% endblock %}
- {% block aa %}
- {% endblock %}
六、数据库连接池
数据库工具:mysql
- import os
- DEBUG=True
- SECRET_KEY=os .urandom(24)
- #
- # DIALECT='mysql'
- # DRIVER='mysqldb'
- # USERNAME='yu'
- # PASSWORD='bozhi'
- # HOST='www.decade.wang'
- # PORT='3306'
- # DATABASE='python'
- SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://yu:bozhi@www.decade.wang:3306/decade?charset=utf8'
- SQLALCHEMY_TRACK_MODIFICATIONS = False
建立连接:
主py
- from werkzeug.security import generate_password_hash,check_password_hash
- from datetime import datetime
- from exts import db
- class User(db.Model):
- __tablename__ = 'user'
- # 建立一个表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)
- image = db.Column(db.String(100))
- say = db.Column(db.String(50))
- @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
- #db.create_all()
- # 建立一表question
- 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'))
- classify=db.Column(db.Enum('散文拾贝', '心灵鸡汤','笑谈风声', '随心所欲'),nullable=False)
- click = db.Column(db.INT, default=0)
- class Comment(db.Model):
- __tablename__ = 'comment'
- # 建立一个表log
- 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('comment',order_by=creat_time.desc))
- author=db.relationship('User',backref=db.backref('comment'))
- #db.create_all()
exts
- from flask_sqlalchemy import SQLAlchemy
- db = SQLAlchemy()
七、通过用户模型,对数据库进行增删改查
- 添加数据
- user=User(username='yujiujiu2',password='11111')
- db.session.add(user)
- db.session.commit()
- 添加数据
- comment=Comment(detail='6666666')
- db.session.add(comment)
- db.session.commit()
- 查找数据
- user=User.query.filter(User.username=='yujiujiu').first()
- print(user.username,user.password)
- 修改数据
- user=User.query.filter(User.username=='yujiujiu').first()
- user.password='666667'
- print(user.username,user.password)
- db.session.commit()
- 删除数据
- user=User.query.filter(User.username=='yujiujiu2').first()
- db.session.delete(user)
- db.session.commit()
八、完成注册功能
1.js文件: onclick函数return True时才提交表单,return False时不提交表单。

- function miao(){
- var oUname=document.getElementById("uname");
- var oUpass=document.getElementById("upass");
- var oUpass2=document.getElementById("upass2");
- var oError=document.getElementById("error_box");
- var isError=true;
- oError.innerHTML="<br>"
- if (oUname.value.length<6 || oUname.value.length>12){
- oError.innerHTML="用户名6-12位";
- isError=false;
- return isError;
- } else if((oUname.value.charCodeAt(0)>=48)&&(oUname.value.charCodeAt(0)<=57)){
- oError.innerHTML="first letter";
- isError=false;
- return isError;
- }
- else for(var i=0;i<oUname.value.length;i++) {
- if (((oUname.value.charCodeAt(i) < 48) || (oUname.value.charCodeAt(i) > 57)) && ((oUname.value.charCodeAt(i) < 97) || (oUname.value.charCodeAt(i) > 122))) {
- oError.innerHTML = "only letter or number";
- isError=false;
- return isError;
- }
- }
- if (oUpass.value.length<6 || oUpass.value.length>12){
- oError.innerHTML="密码6-12位";
- return false;
- }
- else if (oUpass.value!==oUpass2.value){
- oError.innerHTML="两次密码不一致";
- return false;
- }
- return true;
- // window.alert("注册成功!")
- }
- function mySwitch() {
- var oBody = document.getElementById("myBody");
- var oOnOff = document.getElementById("myOnOff");
- var ogui = document.getElementById("gui");
- if (oOnOff.src.match('bulbon')) {
- oOnOff.src = "http://www.runoob.com/images/pic_bulboff.gif";
- oBody.style.backgroundColor = "black";
- oBody.background="../static/img/h.jpg"
- oBody.style.color = "white";
- ogui.src = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1509563443074&di=b1bbb3f5714a580e2211e281124636c2&imgtype=0&src=http%3A%2F%2Fpic15.nipic.com%2F20110709%2F7854247_221301558161_2.jpg";
- } else {
- oOnOff.src = "http://www.runoob.com/images/pic_bulbon.gif";
- oBody.style.backgroundColor = "white";
- oBody.style.color = "black";
- ogui.src = "";
- oBody.background="../static/img/timg1.jpg"
- }
- }

运行结果:
2.html文件:
- <form>中设置 action和method="post"
- <input> 中设置 name

- {% extends 'basic.html'%}
- {% block aa %}
- <link rel="stylesheet" type="text/css" href="{{url_for('static',filename="css/zhuce.css") }}">
- <script language="javascript" type="text/javascript" src="{{url_for('static',filename="js/zhuce.js") }}"></script>
- <div id=mao ><p></p>
- <div id="header"><h2 align="center"></h2></div>
- <div id="content" >
- <form action="{{ url_for('zhuce')}}" method="post"><br/>
- <div class="form-group">
- <label for="uname" class="col-sm-2 control-label">Username:</label>
- <div class="col-sm-10">
- <input type="text" class="form-control" id="uname" name="username"
- placeholder="make your username"><br>
- </div>
- </div>
- <div class="form-group">
- <label for="upass" class="col-sm-2 control-label">Password:</label>
- <div class="col-sm-10">
- <input type="text" class="form-control" id="upass" name="password"
- placeholder="make your password"><br>
- </div>
- </div>
- <div class="form-group">
- <label for="upass2" class="col-sm-2 control-label">AgainPass:</label>
- <div class="col-sm-10">
- <input type="text" class="form-control" id="upass2"
- placeholder="again your password"><br>
- </div>
- </div>
- <div class="form-group1"><label for="question" >SomethingSay</label>
- <textarea class="col-sm-10" rows="3" id="question" name="say"></textarea><br><br><br><br>
- </div>
- <div >
- <br>     <input type="radio" name="role" value="stu">student
- <input id="tea" type="radio" name="role" value="tea">teacher<br/>
- </div>
- <div id="error_box" ></div>
- <div align="center">
- <input id="input_box" type="button" class="btn btn-default btn-lg active" value="注册" onclick="miao()">
- </div>
- </form>
- </div>
- </div>
- {% endblock %}

3.主py文件中:
- from flask import request, redirect, url_for
- @app.route('/regist/', methods=['GET', 'POST’])
- @app.route('/zhuce/',methods=['GET','POST'])
- def zhuce():
- if request.method=='GET':
- return render_template('zhuce.html')
- else:
- username=request.form.get('username')
- password=request.form.get('password')
- say=request.form.get('say')
- user=User.query.filter(User.username==username).first()
- #判断用户名是否存在
- if user:
- return u' username existed'
- else:
- user=User(username=username,password=password,say=say)
- db.session.add(user)
- db.session.commit()
- return redirect(url_for('login'))
- #重新定向到登录页
运行结果:
九、完成登陆功能
登录功能完成:
1.js:设置return
同注册,onclick函数return True时才提交表单,return False时不提交表单。
2.html:设置
- form
- input
- <form action="{{ url_for('login')}}" method="post"><br/>
- <div class="form-group">
- <label for="uname" class="col-sm-2 control-label">Username:</label>
- <div class="col-sm-10">
- <input type="text" class="form-control" id="uname" name="username"
- placeholder="input your username"><br>
- </div>
- </div>
- <div class="form-group">
- <label for="upass" class="col-sm-2 control-label">Password:</label>
- <div class="col-sm-10">
- <input type="password" class="form-control" id="upass" name="password"
- placeholder="input your password"><br>
- </div>
- </div>
- <div >
- <br>       <input type="radio" name="role" value="stu">student 
- <input id="tea" type="radio" name="role" value="tea">teacher<br/><br/>
- </div>
- <div align="center">
- <input id="rem" type="checkbox" value="true"><span>remember me</span>        <a href="http://help.clouddream.net/newsitem/277741776" target="_blank">Login problem</a><br/>
- <br>
- </div>
- <div id="error_box" ></div>
- <div align="center">
- <input id="input_box" type="submit" class="btn btn-default btn-lg active" value="登录" onclick=" return miao()">
- </div>
- </form>
3.py:
- @app.route设置methods
- GET
- POST
- 读取表单数据
- 查询数据库
- 用户名密码对:
- 记住用户名
- 跳转到首页
- 用户名密码不对:
- 提示相应错误。
- 用户名密码对:
- @app.route('/login/',methods=['GET','POST'])
- def login():
- if request.method=='GET':
- return render_template('login.html')
- else:
- usern=request.form.get('username')
- passw=request.form.get('password')
- user=User.query.filter(User.username==usern).first()
- #判断用户名是否存在
- if user:
- session['user']=usern
- session.permanent=True
- if user.password==passw:
- return redirect(url_for('index'))
- else:
- return u' password error'
- else:
- return u' username not existed'
十、登录后更新导航
1.用上下文处理器app_context_processor定义函数
- 获取session中保存的值
- 返回字典
- #判断是否登陆,有则在导航栏显示用户名
- @app.context_processor
- def mycontext():
- usern=session.get('user')
- if usern:
- return {'username':usern}
- else:
- return {}
2.在父模板中更新导航,插入登录状态判断代码。、
- 注意用{% ... %}表示指令。
- {{ }}表示变量
- {% if username %}
- <li><a href="#"><h2>{{ username }}</h2></a></li>
- <li><a href="{{ url_for('logout') }}"><h2>注销</h2></a></li>
- {% else %}
- <li><a href="{{ url_for('login') }}"><h2>登录</h2></a></li>
- <li><a href="{{ url_for('zhuce') }}"><h2>注册</h2></a></li>
- {% endif %}
- <li><a href="#"><h2>联系我</h2></a></li>
- </ul>
- <img id="gui" onclick="mySwitch()" src="" width="1700px">
- {% block aa %}{% endblock %}
3.完成注销功能。
- 清除session
- 跳转
- #登出,清除session
- @app.route('/logout')
- def logout():
- session.clear()
- return redirect(url_for('index'))
十一、完成发布功能
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():
- #发布前登陆装饰器
- def loginFirst(func): # 参数是函数
- @wraps(func)
- def wrapper(*args, **kwargs): # 定义个函数将其返回
- if session.get('user'):
- return func(*args, **kwargs)
- else:
- return redirect(url_for('login'))
- return wrapper # 返回一个函数
3.建立发布内容的对象关系映射。
- class Question(db.Model):
4.完成发布函数。
保存到数据库。
重定向到首页。
- #登陆前验证,进入评论进入问答页
- @app.route('/question/',methods=['GET','POST'])
- @loginFirst
- 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('index'))
十二、在首页显示问答列表
1. 在首页添加显示问答的列表,并定义好相应的样式。
- <ul class="list-group">
- <li class="list-group-item" style="width: 800px">
- {#列表内容开始 #}
- <a class="wrap-img" href="#" target="_blank">
- <img src="http://www.bookmarkye.com/9.jpg" width="50px" >
- </a>
- <span class="glyphicon glyphicon-left" aria-hidden="true"></span>
- <a href="#" target="_blank">{{ user }}</a>
- <br>
- <a href="#">{{ title }}</a>
- <span class="badge">发布时间:{{time }}</span>
- <p style="">{{ detail }}
- </p>
- {# 列表内容结束 #}
- </li>
- </ul>
2. 用字典向index.html传递参数。
- @app.route('/')
- def index():
- context={
- 'user':'yubozhi',
- 'title':'硬盘不是“背锅侠”',
- 'time':'2017-11-29',
- 'detail':'昔日上将悬梁,今天硬盘入党。说这话的是一位资深前媒体人。 光天化日之下,硬盘竟然坏了!众目睽睽之下,硬盘竟然坏了!!大庭广众之下,硬盘竟然坏了!!! 重要的事情说三遍!!! ...',
- }
- return render_template('basic.html',**context)
十三、从首页问答列表标题链接到详情页
1.主PY文件写视图函数,带id参数。
代码如下:

- #进入每篇文章详情页
- @app.route('/detail/<question_id>')
- @loginFirst
- def detail(question_id):
- quest=Question.query.filter(Question.id==question_id).first()
- context={
- 'comments':Comment.query.order_by('-creat_time').all()
- }
- return render_template('detail.html',**context,ques=quest)

2.首页标题的标签做带参数的链接。
代码如下:

- {% for foo in questions %}
- <li class="list-group-item" style="width: 800px">
- <a class="wrap-img" href="#" target="_blank">
- <img src="{{ foo.author.image }}" width="50px">
- </a>
- <span class="glyphicon glyphicon-left" aria-hidden="true"></span>
- <a href="#" target="_blank">{{ foo.author.username }}</a>
- <br>
- <a href="{{ url_for('detail',question_id=foo.id) }}">{{ foo.title }}</a>
- <br>
- <span class="badge">发布时间:{{ foo.creat_time }}</span>
- <p style="">{{ foo.detail }}
- </p>
- {# {{ url_for('usercenter',user_id=foo.author.id) }}#}
- {# <a href="#" target="_blank"><br>评论({{ foo.comments.length }})</a>#}
- </li>
- {% endfor %}

运行结果:
3.在详情页将数据的显示在恰当的位置。
1.首页列表显示全部问答:
- 将数据库查询结果传递到前端页面 Question.query.all()
- 前端页面循环显示整个列表。
- 问答排序
- @app.route('/')
- def index():
- context={
- 'questions':Question.query.order_by('-creat_time').all()
- }
- return render_template('basic.html',**context)
2.完成问答详情页布局:
- 包含问答的全部信息
- 评论区
- 以往评论列表显示区。
代码如下:

- <div class="page-header">
- <h3>{{ ques.title }}<br><br>
- <small>作者:{{ ques.author.username }}   
- <span class="badge">{{ ques.creat_time }}</span>
- </small></h3>
- </div>
- <p class="lead">{{ ques.detail }}</p>
- <hr>
- <form action="{{ url_for('comment') }}" method="post" style="">
- <div class="form-group">
- <input type="text" value="{{ ques.id }}" name="question_id" hidden>
- <input type="text" value="{{ user.id }}" name="author_id" hidden>
- <textarea name="detail" class="form-control" row="3" id="new-comment" placeholder="write your comment"></textarea>
- </div>
- <button type="submit" class="btn btn-default">发送</button>
- </form>
- <hr>

3.在首页点击问答标题,链接到相应详情页。
- #进入每篇文章详情页
- @app.route('/detail/<question_id>')
- def detail(question_id):
- quest=Question.query.filter(Question.id==question_id).first()
- return render_template('detail.html',ques=question_id)
运行结果:
4.建立评论的对象关系映射:
代码如下:

- class Comment(db.Model):
- __tablename__ = 'comment'
- # 建立一个表log
- 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'))

运行结果:
十四、实现发布评论,并显示评论区
代码如下:

- <h3>评论区:
- {# ({{ ques.comments.length }})#}
- </h3><br>
- <div class="basic_box" style="padding-bottom: 50px;">
- <ul class="list-group" style="margin-bottom: 10px">
- {% for qu in comments %}
- <li class="list-group-item" style="width: 800px">
- <a class="wrap-img" href="#" target="_blank">
- <img src="{{ qu.author.image }}" width="50px">
- </a>
- <span class="glyphicon glyphicon-left" aria-hidden="true"></span>
- <br>
- <a href="#">{{ qu.author_id }}</a>
- <span class="badge">评论时间:{{ qu.creat_time }}</span>
- <p style="">{{ qu.detail }}
- </p>
- </li>
- {% endfor %}

运行结果:
十五、完成个人中心相关信息
1.个人中心的页面布局
html文件如下:

- {% extends 'basic.html' %}
- {% block title %} 个人中心{% endblock %}
- {% block aa %}
- <div class="container">
- <div class="row clearfix">
- <div class="col-md-2 column">
- </div>
- <div class="col-md-6 column">
- <h1><img src="{{ img }}" width="50px">{{usern }}</h1>
- <br>全部问答
- <div class="basic_box" style="padding-bottom: 50px;">
- <ul class="list-group">
- {% for qu in ques %}
- <li class="list-group-item" style="width: 800px">
- <a class="wrap-img" href="#" target="_blank">
- <img src="{{ qu.author.image }}" width="50px">
- </a>
- <span class="glyphicon glyphicon-left" aria-hidden="true"></span>
- <a href="{{ url_for('person',user_id=qu.author.id) }}" target="_blank">{{ qu.author.username }}</a>
- <br>
- <a href="{{ url_for('detail',question_id=qu.id) }}">{{qu.title }}</a>
- <br>
- <span class="badge">发布时间:{{ qu.creat_time }}</span>
- <p style="">{{ qu.detail }}
- </p>
- </li>
- {% endfor %}
- </ul>
- </div>
- <h1><img src="{{ img }}" width="50px">{{usern }}</h1>
- <br>全部评论
- <div class="basic_box" style="padding-bottom: 50px;">
- <ul class="list-group" style="margin-bottom: 10px">
- {% for qu in users %}
- <li class="list-group-item" style="width: 800px">
- <a class="wrap-img" href="#" target="_blank">
- <img src="{{ qu.author.image }}" width="50px">
- </a>
- <span class="glyphicon glyphicon-left" aria-hidden="true"></span>
- <br>
- <a href="#">{{ qu.author.username }}</a>
- <span class="badge">评论时间:{{ qu.creat_time }}</span>
- <p style="">{{ qu.detail }}
- </p>
- </li>
- {% endfor %}
- </ul>
- <br>
- <br>
- <h1><img src="{{ img }}" width="50px">{{usern }}</h1>
- <br>个人信息
- <div class="basic_box" style="padding-bottom: 50px;">
- <ul class="list-group" style="margin-bottom: 10px">
- {# {% for qu in users %}#}
- <li class="list-group-item" style="width: 800px"> 用户:{{ usern }}</li>
- <li class="list-group-item" style="width: 800px"> 编号:{{ id }}</li>
- <li class="list-group-item" style="width: 800px"> 问答数:{{ ques|length }}</li>
- <li class="list-group-item" style="width: 800px"> 评论数:{{ comment|length }}</li>
- {# {% endfor %}#}
- </ul>
- </div>
- <div class="col-md-4 column">
- </div>
- </div>
- </div>
- </div>
- </div>
- {% endblock %}

2.定义视图函数def usercenter(user_id):

- # 个人中心
- @app.route('/person/<user_id>',methods=['GET','POST'])
- def person(user_id):
- user = User.query.filter(User.id == user_id).first()
- context = {
- 'img':user.image,
- 'id':user_id,
- 'usern':user.username,
- 'ques': Question.query.filter(Question.author_id == user_id).order_by('-creat_time').all(),
- 'users': Comment.query.filter(Comment.author_id == user_id).order_by('-creat_time').all(),
- 'comment': user.comments
- }
- return render_template('person.html', **context)

3.向前端页面传递参数

- context = {
- 'img':user.image,
- 'id':user_id,
- 'usern':user.username,
- 'ques': Question.query.filter(Question.author_id == user_id).order_by('-creat_time').all(),
- 'users': Comment.query.filter(Comment.author_id == user_id).order_by('-creat_time').all(),
- 'comment': user.comments
- }


- <h1><img src="{{ img }}" width="50px">{{usern }}</h1>
- <br>全部问答
- <h1><img src="{{ img }}" width="50px">{{usern }}</h1>
- <br>全部评论
- <li class="list-group-item" style="width: 800px"> 用户:{{ usern }}</li>
- <li class="list-group-item" style="width: 800px"> 编号:{{ id }}</li>
- <li class="list-group-item" style="width: 800px"> 问答数:{{ ques|length }}</li>
- <li class="list-group-item" style="width: 800px"> 评论数:{{ comment|length }}</li>

4.页面显示相应数据:发布的全部问答、发布的全部评论、个人信息
效果如下:
5.各个页面链接到个人中心
导航栏的昵称连接:

- {% if username %}
- <li><a href="{{ url_for('person',user_id=user.id) }}"><h2>{{ username }}</h2></a></li>
- <li><a href="{{ url_for('logout') }}"><h2>注销</h2></a></li>
- {% else %}
- <li><a href="{{ url_for('login') }}"><h2>登录</h2></a></li>
- <li><a href="{{ url_for('zhuce') }}"><h2>注册</h2></a></li>
- {% endif %}
- <li><a href="{{ url_for('question') }}"><h2>问答</h2></a></li>
- </ul>

主页昵称连接:
- <a href="{{ url_for('person',user_id=foo.author.id) }}" target="_blank">{{ foo.author.username }}</a>
评论列表里面的昵称连接:
- <a href="{{ url_for('person',user_id=qu.author.id) }}">{{ qu.author.username }}</a>
文章中作者名字连接:
- 作者:<a href="{{ url_for('person',user_id=ques.author.id) }}">{{ ques.author.username }}</a>
6.新页面user.html,用<ul ><li role="presentation"> 实现标签页导航。
<ul class="nav nav-tabs">
<li role="presentation"><a href="#">Home</a></li>
<li role="presentation"><a href="#">Profile</a></li>
<li role="presentation"><a href="#">Messages</a></li>
</ul>

- <ul class="nav nav-tabs">
- <li class="nav" role="presentation"><a href="#"><h3>全部问答</h3></a></li>
- <li class="nav" role="presentation"><a href="#"><h3>全部评论</h3></a></li>
- <li class="nav" role="presentation"><a href="#"><h3>个人中心</h3></a></li>
- </ul>

7.user.html继承base.html。
重写title,head,main块.
将上述<ul>放在main块中.
定义新的块user。
如下:
user.html

- {% extends 'basic.html' %}
- {% block title %} 个人中心{% endblock %}
- {% block aa %}
- {% block user %}{% endblock %}
- </div>
- {% endblock %}

person.html
- {% extends 'user.html' %}
- {% block user %}
- {% endblock %}
8.个人中心—视图函数带标签页面参数tag
@app.route('/usercenter/<user_id>/<tag>')
def usercenter(user_id, tag):
if tag == ‘1':
return render_template('usercenter1.html', **context)

- # 个人中心
- @app.route('/person/<user_id>/<tag>',methods=['GET','POST'])
- def person(user_id,tag):
- user = User.query.filter(User.id == user_id).first()
- context = {
- 'img':user.image,
- 'id':user_id,
- 'usern':user.username,
- 'ques': Question.query.filter(Question.author_id == user_id).order_by('-creat_time').all(),
- 'users': Comment.query.filter(Comment.author_id == user_id).order_by('-creat_time').all(),
- 'comment': user.comments,
- 'user1':user
- }
- if tag=='1':
- return render_template('person.html', **context)
- elif tag=='2':
- return render_template('person2.html', **context)
- else:
- return render_template('person3.html', **context)

9.个人中心—导航标签链接增加tag参数
<li role=“presentation”><a href=“{{ url_for(‘usercenter’,user_id = user.id,tag = ‘1’) }}">全部问答</a></li>
- <li class="nav" role="presentation"><a href="{{url_for('person',user_id=user1.id,tag=1)}}"><h3>全部问答</h3></a></li>
- <li class="nav" role="presentation"><a href="{{url_for('person',user_id=user1.id,tag=2)}}"><h3>全部评论</h3></a></li>
- <li class="nav" role="presentation"><a href="{{url_for('person',user_id=user1.id,tag=3)}}"><h3>个人中心</h3></a></li>
10.个人中心—有链接到个人中心页面的url增加tag参数
u <a href="{{ url_for('usercenter',user_id = session.get('userid'), tag=1) }}">{{ session.get('user') }}</a>

- <a href="{{ url_for('person',user_id=qu.author.id,tag=1) }}" target="_blank">{{ qu.author.username }}</a>
- <a class="wrap-img" href="{{ url_for('person',user_id=foo.author.id,tag=1) }}" target="_blank">
- <a href="{{ url_for('person',user_id=foo.author.id,tag=1) }}" target="_blank">{{ foo.author.username }}</a>

运行结果:
十六、实现导航条中的搜索功能
1.准备视图函数search()
- # 查找
- @app.route('/search/')
- def search():
- p
Python+Flask+MysqL的web建设技术过程的更多相关文章
- 个人学期总结及Python+Flask+MysqL的web建设技术过程
一个学期即将过去,我们也迎来了2018年.这个学期,首次接触了web网站开发建设,不仅是这门课程,还有另外一门用idea的gradle框架来制作网页. 很显然,用python语言的flask框架更加简 ...
- Python+Flask+MysqL的web技术建站过程
1.个人学期总结 时间过得飞快,转眼间2017年就要过去.这一年,我学习JSP和Python,哪一门都像一样新的东西,之前从来没有学习过. 这里我就用我学习过的Python和大家分享一下,我是怎么从一 ...
- 前端和后端的数据交互(jquery ajax+python flask+mysql)
上web课的时候老师布置的一个实验,要求省市连动,基本要求如下: 1.用select选中一个省份. 2.省份数据传送到服务器,服务器从数据库中搜索对应城市信息. 3.将城市信息返回客户,客户用sele ...
- 实战接口开发:python + flask + mysql + redis(根据反馈,持续细化更新。。。)
前言 自动化已经成为测试的必备技能之一了,所以,很多想跳槽的测试朋友都在自学,特别是最实用的接口自动化, 但是很多人因为没有可以练手的项目而苦恼,最终导致缺乏实战经验,其实,完全可以自己开发个简单项目 ...
- Python Flask+Mysql练习题
#!/usr/bin/pythonfrom flask import Flask,render_template,request,redirect,sessionimport MySQLdb as m ...
- Python flask 与 GO WEB服务器性能对比
测试环境: 系统: CentOS 7.1 Mem: 8G CPU: 虚拟机16核 Python版本: python3.6 Flask版本: 0.12.2 Golang版本: 1.6.3 1.首先写一个 ...
- 使用 Python & Flask 实现 RESTful Web API
环境安装: sudo pip install flask Flask 是一个Python的微服务的框架,基于Werkzeug, 一个 WSGI 类库. Flask 优点: Written in Pyt ...
- demo项目开发(Python+flask+mysql+redis只包含后端接口)
[demo项目开发需求] 用户信息管理,可以注册.登录.添加用户.删除用户 注册:任何用户可以注册,对用户提交的注册信息进行校验,返回对应的信息,其中: 用户名:必填,唯一 密码:必填,只能6-12位 ...
- Python flask 基于 Flask 提供 RESTful Web 服务
转载自 http://python.jobbole.com/87118/ 什么是 REST REST 全称是 Representational State Transfer,翻译成中文是『表现层状态转 ...
随机推荐
- IIS7.5站点配置
1. 创建站点映射目录: c:\website\release 2. 创建系统用户: a.本地用户和组-->用户-->新用户-->用户名\密码:WebUSR.xxxyyy--> ...
- api收录
ip地址查询api http://ip.taobao.com/service/getIpInfo.php?ip= 如: http://ip.taobao.com/service/getIpInfo.p ...
- mysql 数据操作 单表查询 where 约束 目录
mysql 数据操作 单表查询 where约束 between and or mysql 数据操作 单表查询 where约束 is null in mysql 数据操作 单表查询 where约束 li ...
- python之celery队列模块
一.celery队列简介 Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery. 1 ...
- 【转】Deep Learning(深度学习)学习笔记整理系列之(四)
九.Deep Learning的常用模型或者方法 9.1.AutoEncoder自动编码器 Deep Learning最简单的一种方法是利用人工神经网络的特点,人工神经网络(ANN)本身就是具有层次结 ...
- 网络协议TCP、Http、webservice、socket区别
网络协议TCP.Http.webservice.socket区别 http 和 webservice 都是基于TCP/IP协议的应用层协议 webservice是基于http的soap协议传输数据 w ...
- hdu4758 Walk Through Squares
地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=4758 题目: Walk Through Squares Time Limit: 4000/20 ...
- DB 异常
1. ORA-00947: Not enough values 没有足够的值 执行insert的时候出现这个错误. 例如:insert into 表1 values (?,?,?); 表1的结构有4 ...
- React 根据 state 修改className
className={ this.state.isLike ? 'active iconfont icon-xihuan' : 'iconfont icon-xihuan1' }
- DB开发之postgresql
1.环境变量配置: PGLIB=/usr/local/pgsql/lib PGDATA=$HOME/data PATH=$PATH:/usr/local/pgsql/bin MANPATH=$MANP ...