连接数据库的频率很高,所以把数据库操作封装起来

函数封装:

def make_dicts(cursor, row):
""" 将游标获取的Tuple根据数据库列表转换为dict """
return dict((cursor.description[idx][0], value) for idx, value in enumerate(row)) def get_db():
""" 获取(简历数据库链接)
g: flask内置的变量:g = LocalProxy(partial(_lookup_app_object, "g"))
"""
db = getattr(g, '_database', None)
if not db:
db = g._database = sqlite3.connect(DATABASE)
db.row_factory = make_dicts
return db def execute_sql(sql, params=()):
""" 执行sql语句不返回数据结果 insert、update、delete """
c = get_db().cursor()
c.execute(sql, params)
c.connection.commit() def query_sql(sql, params=(), one=False):
""" 查询数据 one=False的时候返回多条"""
c = get_db().cursor()
result = c.execute(sql, params).fetchall()
c.close()
return (result[0] if result else None) if one else result @app.teardown_appcontext # 在当前app上下文销毁时执行
def close_connection(exeption):
""" 关闭数据库 """
db = getattr(g, '_database', None)
if db is not None:
db.close()

修改之前的数据库操作为用函数

由于返回参数从元祖变为了字典,所以要修改前端渲染取值方式,从元祖取值改为字典取值

列表展示页:feedback-list.html

{% extends 'base.html'%}

{% block main_content %}
<div class="row">
<table class="table table-hover">
<tr>
<th>ID</th>
<th>主题</th>
<th>分类</th>
<th>用户</th>
<th>邮箱</th>
<th>处理状态</th>
<th>提交时间</th>
<th>操作</th>
</tr>
{% for item in items %}
<tr>
<td>{{ loop.index }}</td><!--jinja模板提供的遍历序号功能-->
<td>{{ item.Subjeck }}</td><!--jinja模板提供的字典取值功能-->
<td>{{ item.get('CategoryID', 0) }}</td><!--python自带的字典取值功能-->
<td>{{ item['UserName'] }}</td><!--python自带的字典取值功能-->
<td>{{ item['Email'] }}</td>
<td><span class="label label-{{ 'danger' if item['State'] ==0 else 'success' }}">{{ "未处理" if item['State'] ==0 else "已处理" }}</span></td>
<td>{{ item['ReleaseTime'] }}</td>
<td>
<a href="#" class="btn btn-success">查看</a>
<a href="{{ url_for('edit', id=item['rowid']) }}" class="btn btn-default">编辑</a>
<a href="{{ url_for('delete_feedback', id=item['rowid']) }}" class="btn btn-danger">删除</a>
</td>
</tr>
{% endfor %}
</table>
</div> {% endblock %}

编辑页:edit.html

<!--继承base.html-->
{% extends 'base.html' %} <!--引用base.html预留的正文部分-->
{% block main_content %}
<div class="row">
<div class="panel panel-default">
<div class="panel-heading">
<h4>问题反馈信息编辑</h4>
</div>
<div class="panel-body">
<!--保存的url-->
<form action="{{ url_for('save_edit') }}" method="POST" class="form-horizontal">
<div class="form-group">
<label for="subject" class="control-label col-md-2">主题</label>
<div class="col-md-6">
<!--渲染主题-->
<input type="text" value="{{ item['Subjeck'] }}" class="form-control" id="subject" name="subject">
<!--拿到id,不渲染,用于保存的时候做sql条件-->
<input type="hidden" value="{{ item['rowid'] }}" class="form-control" id="rowid" name="rowid">
</div>
</div>
<div class="form-group">
<label for="category" class="control-label col-md-2">问题分类</label>
<div class="col-md-2">
<select name="category" id="category" class="form-control">
<!--显示当前问题的问题分类-->
{% for category in categories %}
<option {{ 'selected=selected' if item['CategoryID']==category['rowid'] else '' }} value="{{ category['rowid'] }}">{{ category['CategoryName'] }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label for="username" class="control-label col-md-2">姓名</label>
<div class="col-md-2">
<!--渲染姓名-->
<input type="text" class="form-control" value="{{ item['UserName'] }}" id="username" name="username">
</div>
</div>
<div class="form-group">
<label for="email" class="control-label col-md-2">邮箱</label>
<div class="col-md-6">
<!--渲染邮箱-->
<input type="text" class="form-control" value="{{ item['Email'] }}" id="email" name="email">
</div>
</div>
<div class="form-group">
<label for="image" class="control-label col-md-2">图片</label>
<div class="col-md-6">
<input type="file" id="image" name="image">
</div>
</div> <div class="form-group">
<!--渲染内容-->
<label for="body" class="control-label col-md-2">内容</label>
<div class="col-md-6">
<textarea name="body" id="body" cols="30" rows="10" class="form-control">{{ item['Body'] }}</textarea>
</div>
</div>
<!--增加回复内容、发布时间和处理状态-->
<div class="form-group">
<label for="reply" class="control-label col-md-2">回复</label>
<div class="col-md-6">
<!--渲染回复-->
<textarea name="reply" id="reply" cols="30" rows="10" class="form-control">{{ item['Reply'] if item['Reply'] }}</textarea>
</div>
</div>
<div class="form-group">
<label for="releasetime" class="control-label col-md-2">发布时间</label>
<div class="col-md-6">
<input type="text" value="{{ item['ReleaseTime'] }}" name="releasetime" id="releasetime" class="form-control">
</div>
</div>
<div class="form-group">
<label for="state" class="control-label col-md-2">处理状态</label>
<div class="col-md-6">
<!--渲染处理状态-->
<input type="checkbox" name="state" id="state" {{ 'checked=checked' if item['State'] == 1 else ''}} >
</div>
</div> <div class="col-md-offset-2">
<input type="submit" class="btn btn-primary" value="提交">
<input type="reset" class="btn btn-default" value="重置">
<!--如果不想修改了,点击回到列表页-->
<a href="{{ url_for('list') }} " class="btn btn-default">点击回到列表页</a>
</div>
</form>
</div>
<div class="panel-footer"> </div>
</div>
</div> {% endblock %}

页面渲染

后台打印的数据

编辑页面

程序入口:main.py

# coding:utf-8
import sqlite3
from datetime import datetime
from flask import Flask, request, render_template, redirect, url_for, g app = Flask(__name__) DATABASE = r'.\db\feedbach.db' '=======================封装sql助手函数=============================' def make_dicts(cursor, row):
""" 将游标获取的Tuple根据数据库列表转换为dict """
return dict((cursor.description[idx][0], value) for idx, value in enumerate(row)) def get_db():
""" 获取(简历数据库链接)
g: flask内置的变量:g = LocalProxy(partial(_lookup_app_object, "g"))
"""
db = getattr(g, '_database', None)
if not db:
db = g._database = sqlite3.connect(DATABASE)
db.row_factory = make_dicts
return db def execute_sql(sql, params=()):
""" 执行sql语句不返回数据结果 insert、update、delete """
c = get_db().cursor()
c.execute(sql, params)
c.connection.commit() def query_sql(sql, params=(), one=False):
""" 查询数据 one=False的时候返回多条"""
c = get_db().cursor()
result = c.execute(sql, params).fetchall()
c.close()
return (result[0] if result else None) if one else result @app.teardown_appcontext # 在当前app上下文销毁时执行
def close_connection(exeption):
""" 关闭数据库 """
db = getattr(g, '_database', None)
if db is not None:
db.close() '========================================================================' @app.route("/")
def index():
return render_template('base.html') # 模板继承
@app.route("/feedback/")
def feedback():
return render_template('post.html') @app.route("/post_feedback/", methods=["POST"])
def post_feedback():
""" 提交视图 """
if request.method == 'POST': # 如果是post请求就获取表单值
subject = request.form.get('subject', None)
categoryid = request.form.get('category', 1)
username = request.form.get('username')
email = request.form.get('email')
body = request.form.get('body')
release_time = str(datetime.now())
state = 0
print(subject, categoryid, username, email, body, state, release_time)
conn = sqlite3.connect(DATABASE)
c = conn.cursor()
# 防止sql注入,用?代替值
sql = "insert into feedback (Subjeck, CategoryID, UserName, Email, Body, State, ReleaseTime) values (?,?,?,?,?,?,?)"
c.execute(sql, (subject, categoryid, username, email, body, state, release_time))
conn.commit()
conn.close()
# 为防止因卡顿引起重复提交,提交过后跳转到填写页面
return redirect(url_for('feedback')) @app.route("/list/")
def list():
""" 展示所有问题 """
sql = "select ROWID,* from feedback order by ROWID DESC"
feedbacks = query_sql(sql)
print(feedbacks)
return render_template('feedback-list.html', items=feedbacks) @app.route('/del/<id>/')
def delete_feedback(id=0):
""" 删除问题 ,前端传id"""
conn = sqlite3.connect(DATABASE)
c = conn.cursor()
sql = "delete from feedback where ROWID = ?"
c.execute(sql, (id,))
conn.commit()
conn.close()
return redirect(url_for('list')) # 编辑功能
@app.route("/edit/<id>/")
def edit(id=None):
""" 根据前端传过来的id返回编辑的html """
# 获取绑定的下拉列表
sql = "select ROWID,CategoryName from category"
categories = query_sql(sql)
# 获取当前id的信息,并绑定至form表单,以备修改
sql = "select rowid,* from feedback where rowid = ?"
curren_feedback = query_sql(sql, (id,), True)
# return str(curren_feedback) # 查看查出来的数据顺序,方便html渲染排序
return render_template('edit.html', categories=categories, item=curren_feedback) @app.route("/save_edit/", methods=['POST'])
def save_edit():
""" 保存编辑 """
if request.method == 'POST':
id = request.form.get('rowid', None)
reply = request.form.get('reply')
state = 1 if request.form.get('state', 0) == 'on' else 0
sql = 'update feedback set Reply=?, State=? where rowid=?'
conn = sqlite3.connect(DATABASE)
c = conn.cursor()
c.execute(sql, (reply, state, id))
conn.commit()
conn.close()
return redirect(url_for('list')) if __name__ == '__main__':
app.run(
debug=True
)

测开之路一百三十三:实现sql函数封装的更多相关文章

  1. 测开之路一百五十三:ajax之load、get、ajax在项目中的体现

    在查询的时候是使用ajax进行请求的 目录结构 personal.models from datetime import datetimefrom flask_sqlalchemy import SQ ...

  2. 测开之路一百三十九:会话管理之cookie写入、读取、和更新

    机制:服务器端发送的小段文本信息存储在客户端硬盘 功能:记录用户偏好,请求.页面.站点间共享信息 特点:易丢失.安全隐患 添加cookie,需要用到make_respons.set_cookie @a ...

  3. 测开之路一百三十八:会话管理之session

    session管理和使用,需要用到flask的session模块和设置安全码:app.secret_key 比如列表页和编辑功能只能给admin用 列表页 编辑页 添加session 登录成功时,把u ...

  4. 测开之路一百二十三:快速搭建python虚拟环境

    前提:已装好python3.4+且环境可正常运行 一:手动搭建: 准备好一个工作目录 管理员运行cmd,进入到准备的目录里面 执行命令:python -m venv 虚拟环境名 激活虚拟环境(在ven ...

  5. 测开之路一百零三:jquery元素和标签的插入与删除

    标签内插入 标签外插入 给标签加标签 !DOCTYPE html><html lang="en"><head> <meta charset=&q ...

  6. 测开之路一百五十二:基于jquery的ajax实现之load、get、ajax

    ajax除了用原生的js实现之外,也可以使用jquery实现,而且用jquery更方便 看一个简单的示例,保留上一篇的content路由和html,实现上一篇一样的功能,点击获取内容,局部刷新 准备一 ...

  7. 测开之路一百零六:bootstrap布局

    可以在html的head里面加一些说明 <meta http-equiv="X-UA-Compatible" content="IE=edge">& ...

  8. 测开之路一百零二:jquery元素操作

    jquery对元素操作,获取/替换文本(.text()).html(.html()).属性(.attr()).值(.val()) html代码 text() 根据标签获取文本值 同一个标签下筛选明细 ...

  9. 测开之路一百五十五:jquery-validation前台数据验证

    前面做的wtform验证是服务器端的验证,需要把数据传输到服务器,服务器验证后再吧结果传输到前端,网络慢的时候,用户体验不好,所以需要前端验证,且后端验证不能少 传统的js或者jquery如果要验证信 ...

随机推荐

  1. 初探html-17 表单

    HTML 表单和输入 HTML 表单用于收集不同类型的用户输入. 在线实例 <form action=""> First name: <input type=&q ...

  2. 自己对GIS的思考

    这只是我自己的理解,谈不上对整个行业的理解,只能从自己的角度谈谈GIS,谈谈爱和恨. 现在在武汉的一所所谓的全国GIS数一数二的学校里面读硕士,从高中开始我就很喜欢地理学科,大学选择了地球信息科技这个 ...

  3. jQuery+Ajax实现图片的预览和上传

    jQuery+Ajax实现图片的预览和上传 1.配置Spring-web.xml <!-- springmvc上传图片 --> <bean id="multipartRes ...

  4. C/C++ 零碎知识点

    传递参数的一般指导原则: 对于使用传递的值而不做修改的函数: 如果数据对象很小,比如内置类型或者小型结构,按值传递. 如果数据对象是数组,只能使用指针,并将指针生命为指向const的指针. 如果数据对 ...

  5. Laravel5.5去除URL中的index.php生成优雅链接

    在使用Apache情况下: Laravel 框架通过 public/.htaccess 文件来让网址中不需要 index.php.如果你的服务器是使用 Apache ,请确认是否有开启 mod_rew ...

  6. safari兼容时间格式 NAN

    问题: safari中不支持2018-08-01这种格式转为时间戳会显示NaN 方案: new Date('2018/08/01').getTime() 将-转化为/ // 正则替换 new Date ...

  7. Hive 中的 LEFT SEMI JOIN 与 JOIN ON

    hive 的 join 类型有好几种,其实都是把 MR 中的几种方式都封装实现了,其中 join on.left semi join 算是里边具有代表性,且使用频率较高的 join 方式. 1.联系 ...

  8. springMVC项目访问URL链接时遇到某一段然后忽略后面的部分

    背景:一个链接URL:http:localhost/tq/asf/218732,配置URL使遇到/asf后直接跳转不识别/asf后面的218732 因为是在ssm框架下做的项目,所以用spring的注 ...

  9. SpringCloud学习系列-Eureka服务注册与发现(2)

    构建 microservicecloud-eureka-7001 eureka服务注册中心Module 1.新建microservicecloud-eureka-7001 2.pom <proj ...

  10. shiro框架学习-7- Shiro权限控制注解和编程方式

    讲解权限角色控制 @RequiresRoles, @RequiresPermissions等注解的使用和编程式控制 配置文件的方式 使用ShiroConfig 注解方式 @RequiresRoles( ...