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

函数封装:

  1. def make_dicts(cursor, row):
    """ 将游标获取的Tuple根据数据库列表转换为dict """
    return dict((cursor.description[idx][0], value) for idx, value in enumerate(row))
  2.  
  3. 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
  4.  
  5. def execute_sql(sql, params=()):
    """ 执行sql语句不返回数据结果 insert、update、delete """
    c = get_db().cursor()
    c.execute(sql, params)
    c.connection.commit()
  6.  
  7. 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
  8.  
  9. @app.teardown_appcontext # 在当前app上下文销毁时执行
    def close_connection(exeption):
    """ 关闭数据库 """
    db = getattr(g, '_database', None)
    if db is not None:
    db.close()

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

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

列表展示页:feedback-list.html

  1. {% extends 'base.html'%}
  2.  
  3. {% 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>
  4.  
  5. {% endblock %}

编辑页:edit.html

  1. <!--继承base.html-->
    {% extends 'base.html' %}
  2.  
  3. <!--引用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>
  4.  
  5. <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>
  6.  
  7. <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">
  8.  
  9. </div>
    </div>
    </div>
  10.  
  11. {% endblock %}

页面渲染

后台打印的数据

编辑页面

程序入口:main.py

  1. # coding:utf-8
    import sqlite3
    from datetime import datetime
    from flask import Flask, request, render_template, redirect, url_for, g
  2.  
  3. app = Flask(__name__)
  4.  
  5. DATABASE = r'.\db\feedbach.db'
  6.  
  7. '=======================封装sql助手函数============================='
  8.  
  9. def make_dicts(cursor, row):
    """ 将游标获取的Tuple根据数据库列表转换为dict """
    return dict((cursor.description[idx][0], value) for idx, value in enumerate(row))
  10.  
  11. 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
  12.  
  13. def execute_sql(sql, params=()):
    """ 执行sql语句不返回数据结果 insert、update、delete """
    c = get_db().cursor()
    c.execute(sql, params)
    c.connection.commit()
  14.  
  15. 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
  16.  
  17. @app.teardown_appcontext # 在当前app上下文销毁时执行
    def close_connection(exeption):
    """ 关闭数据库 """
    db = getattr(g, '_database', None)
    if db is not None:
    db.close()
  18.  
  19. '========================================================================'
  20.  
  21. @app.route("/")
    def index():
    return render_template('base.html')
  22.  
  23. # 模板继承
    @app.route("/feedback/")
    def feedback():
    return render_template('post.html')
  24.  
  25. @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'))
  26.  
  27. @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)
  28.  
  29. @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'))
  30.  
  31. # 编辑功能
    @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)
  32.  
  33. @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'))
  34.  
  35. 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. 为了实现动态加载而编写的自己的ClassLoader

    Copy备用 之前客户要求在不重启应用的前提下实现动态增加服务及交易,在网上查了很长时间也没发现类似的技术,最后研究了一下ClassLoader.因为项目是与Spring,一开始我和同事尝试替换源码的 ...

  2. Python控制语句执行流程

    if语句: if<条件>:#条件之后必须有“:”.  <语句> if语句的三元运算符: <表达式1>if<条件>else<表达式2>:其语义 ...

  3. Android 静态代码分析工具

    简评: 作者在文中提到的三个静态代码分析工具不是互相替代的关系,各有各的侧重点,如果有需要完全可以同时使用. 静态代码分析是指无需运行被测代码,仅通过分析或检查源程序的语法.结构.过程.接口等来检查程 ...

  4. IO模型对比:同步、异步、阻塞、非阻塞

    最近工作接触到了网络服务同步和异步,所以学习了下<UNIX网络编程>,在此作下总结. 一.I/O模型 输入/输出(I/O)是在主存和外部设备(如磁盘驱动器.终端和网络)之间拷贝数据的过程. ...

  5. 单调队列优化DP || [Poi2014]Little Bird || BZOJ 3831 || Luogu P3572

    题面:[POI2014]PTA-Little Bird 题解: N<=1e6 Q<=25F[i]表示到达第i棵树时需要消耗的最小体力值F[i]=min(F[i],F[j]+(D[j]> ...

  6. Codeforces Round #569 (Div. 2) B. Nick and Array

    链接: https://codeforces.com/contest/1180/problem/B 题意: Nick had received an awesome array of integers ...

  7. rsync快速部署记录

    rsync快速部署记录 安装rsync和使用环境:客户端:10.192.30.59 fudao_db_cluster_002 (将本地文件备份到服务端)服务端:10.192.30.60 fudao_d ...

  8. 【ZJOI2009】狼和羊的故事

    题目 "狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......" Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! ...

  9. mssql因为手贱修改了服务配置的最大内存,造成无法启动

    mssql数据库设置内存太小,造成无法启动服务. 解决办法: 1.用命令行形式启动最精简版的mssql服务,另外再用一个新的命令行去修改配置,将内存设置为无限制.  命令行要记得用管理员身份运行比较稳 ...

  10. eclipse在线安装ermaster插件

    eclipse在线安装ermaster插件: https://www.jianshu.com/p/449fbcd9141a ERMaster的安装和使用 https://www.cnblogs.com ...