session管理和使用,需要用到flask的session模块和设置安全码:app.secret_key

比如列表页和编辑功能只能给admin用

列表页

编辑页

添加session

登录成功时,把username添加到session里面

app.secret_key = 'qoihf2397r21380r2/./ad'  # 加密的安全码,越复杂越好,flask后台自动进行加密

@app.route('/login/', methods=['GET', 'POST'])
def login():
""" 登录 """
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
sql = 'select count(*) as [Count] from UserInfo where username = ? and password = ?'
result = query_sql(sql, (username, password), True)
if int(result.get('Count')) > 0:
print(username)
session['admin'] = username # 已登录的用户保存到session
return redirect(url_for('list'))
return '用户名或密码错误'
return render_template('login.html')

base模板设置显示登录角色

数据库有两个账号

登录Jerry

登录Admin

删除session

@app.route('/logout/')
def logout():
""" 退出登录,删除session跳转到登录页 """
session.pop('admin')
return redirect(url_for('list')) # 为了防止在页面上点后退的情况,让list视图来执行让页面跳转到登录页

base.html

执行退出

base.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>-问题反馈系统</title>
<!--bootstrap、jquery、font-awesome-->
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>
<link href="https://cdn.bootcss.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<!--导航栏-->
<div class="row">
<nav class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1--collapse">
<span class="sr-only"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">问题反馈系统</a>
</div>
<div class="collapse navbar-collapse navbar-ex1--collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="{{ url_for('feedback') }}">首页</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">反馈管理<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="{{ url_for('list') }}">问题列表</a></li>
</ul>
</li>
</ul>
<form class="navbar-form navbar-left" role="search">
<div class="for-group">
<input type="text" class="form-control" placeholder="Search">
<button type="submit" class="btn btn-default">submit</button>
</div>
</form>
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ session['admin'] if session['admin'] else '未登录' }}<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="{{ url_for('logout') }}">退出</a></li>
</ul>
</li>
</ul>
</div>
</nav>
</div> <!--面包屑导航-->
<div class="row">
<ul class="breadcrumb">
<li><a href="/">首页</a></li>
<li class="active">问题反馈</li>
</ul>
</div> <!--正文部分预留空间,其他页面只需要继承过后往这里面添加内容即可-->
{% block main_content %} {% endblock %} <!--页脚-->
<div class="row">
<div class="well text-center">
&copy;版权所有 <a href="https://www.baidu.com/">点击跳转</a>
</div>
</div>
</div>
</body>
</html>

视图

# coding:utf-8
import sqlite3
from datetime import datetime
from flask import Flask, request, render_template, redirect, url_for, g, send_from_directory, session 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.secret_key = 'qoihf2397r21380r2/./ad' # 加密的安全码,越复杂越好,flask后台自动进行加密 @app.route('/login/', methods=['GET', 'POST'])
def login():
""" 登录 """
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
sql = 'select count(*) as [Count] from UserInfo where username = ? and password = ?'
result = query_sql(sql, (username, password), True)
if int(result.get('Count')) > 0:
print(username)
session['admin'] = username # 已登录的用户保存到session
return redirect(url_for('list'))
return '用户名或密码错误'
return render_template('login.html') # 模板继承
@app.route("/feedback/")
def feedback():
return render_template('post.html') UPLOAD_FOLDER = r'.\uploads' # 声明存文件的目录
ALLOWED_EXTENSIONS = ['.jpg', '.png', '.gif'] # 允许上传的后缀,限制上传格式 import os def allowed_file(filename):
""" 判断文件是否允许上传 """
# filename = 'asdasdasd.jpg'
_, ext = os.path.splitext(filename)
return ext.lower() in ALLOWED_EXTENSIONS # 把后缀转为小写 @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
img_path = None
# 提交的内容包含图片,就获取图片名字用于插入数据库,并保存图片
if request.files.get('file_s', None):
img = request.files['file_s']
if allowed_file(img.filename):
# 为防止文件名重复,重命名文件
img_path = datetime.now().strftime('%Y%m%d%H%M%f') + os.path.splitext(img.filename)[1]
img.save(os.path.join(UPLOAD_FOLDER, img_path))
print(subject, categoryid, username, email, body, state, release_time, img_path)
conn = sqlite3.connect(DATABASE)
c = conn.cursor()
# 防止sql注入,用?代替值
sql = "insert into feedback (Subjeck, CategoryID, UserName, Email, Body, State, ReleaseTime, Image) values (?,?,?,?,?,?,?,?)"
c.execute(sql, (subject, categoryid, username, email, body, state, release_time, img_path))
conn.commit()
conn.close()
# 为防止因卡顿引起重复提交,提交过后跳转到填写页面
return redirect(url_for('feedback')) @app.route("/list/")
def list():
""" 展示所有问题 """
# 访问/list/的时候,如果session里面没有admin,就返回登录页
if session.get('admin', None) is None:
return redirect(url_for('login'))
key = request.args.get('key', '')
sql = 'select f.ROWID,f.*,c.CategoryName from feedback f INNER JOIN category c on c.ROWID = f.CategoryID where f.Subjeck like ? order by f.ROWID'
feedbacks = query_sql(sql, (f'%{key}%',))
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('/profile/<filename>')
def render_file(filename):
""" 呈现特定目录下的资源,用于jinja2模板调用渲染服务器的图片"""
return send_from_directory(UPLOAD_FOLDER, filename) # uploads + feilename @app.route("/edit/<id>/")
def edit(id=None):
""" 根据前端传过来的id返回编辑的html """
# 访问/edit/<id>/的时候,如果session里面没有admin,就返回登录页
if session.get('admin', None) is None:
return redirect(url_for('login'))
# 获取绑定的下拉列表
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')) @app.route('/logout/')
def logout():
""" 退出登录,删除session跳转到登录页 """
session.pop('admin')
return redirect(url_for('list')) # 为了防止在页面上点后退的情况,让list视图来执行让页面跳转到登录页 if __name__ == '__main__':
app.run(
debug=True
)

测开之路一百三十八:会话管理之session的更多相关文章

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

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

  2. 测开之路一百二十八:flask之重定向和404

    a.b两个视图,分别返回a的页面和b的页面 重定向:redirect 重定向到路由:请求/a/时,重定向到/b/ 重定向到视图函数:url_for(“函数名“),访问/a/时,重定向到函数b() 主动 ...

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

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

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

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

  5. 测开之路一百五十四:ajax+json前后台数据交互

    在实际工作中,前后端数据交互大部分都是用的json格式,后端把数据处理完后,把json传给前端,前端再解析 项目结构 models里面加入把数据转为字典的方法 from datetime import ...

  6. 测开之路一百四十八:WTForms表单验证

    使用WTForms表单验证,可以在数据建模时就设置验证信息和错误提示 创建模型时,设置验证内容,如必填.格式.长度 from flask_wtf import Formfrom wtforms imp ...

  7. 测开之路一百三十三:实现sql函数封装

    连接数据库的频率很高,所以把数据库操作封装起来 函数封装: def make_dicts(cursor, row): """ 将游标获取的Tuple根据数据库列表转换为d ...

  8. 测开之路一百二十九:jinja2模板语法

    flask用的是jinja2模板,有自己特定的语法 形参: 在html里面留占位参数: {{ 参数名 }},后端传值时,参数名=参数值 <!DOCTYPE html><html la ...

  9. 测开之路一百二十六:flask之获取request请求数据

    可以根据flask的request对象获取所有的请求信息 path = request.path # 获取请求地址method = request.method # 获取请求方法ip = reques ...

随机推荐

  1. 搭建CocoaPods远程私有库

    1.创建自己的远程私有索引库,用来存放私有框架的.podspec文件,并将其添加到本地索引 我用的仓库是码云(https://gitee.com),用自己的账号新建一个私有仓库,我命名为Private ...

  2. iPhone屏幕适配,历史及现状(http://hjcapple.github.io/2014/10/10/iphone-screen.html)

    iPhone屏幕适配,历史及现状 初代iPhone 2007年,初代iPhone发布,屏幕的宽高是320×480像素.下文也是按照宽度,高度的顺序排列.这个分辨率一直到iPhone 3GS的也保持不变 ...

  3. 第五小节之JAVA IO流

    文件:文本文件是一种计算机文件,它是一种典型的顺序文件,其文件的逻辑结构又属于流式文件,特别的是指以ASCLL码方式(也称为文本方式)存储的文件,而更确切地说,英文.数字等字符存储的是ASCLL码,而 ...

  4. sed编辑

    data4.txt this is a test of the test scriptthis is the second test of the trial script data6.txt thi ...

  5. 大数据之Linux

    1 Linux的入门 1.1 概述 Linux内核最初只是由芬兰人林纳斯·托瓦兹(Linus Torvalds)在赫尔辛基大学上出于个人爱好而编写的. Linux是一套免费使用和自由传播的类Unix操 ...

  6. 微信小程序中的自定义组件(components)

     其实小程序开发很像vue和react的结合,数据绑定和setData  重新渲染页面的数据,最近发现连写组件都是很像,也是醉了,自我认为哈, 因为小程序可以将页面内的功能模块抽象成自定义组件,以便在 ...

  7. java数据结构3--List

    List 1.1 list接口的简介 1.2 list实现子类 ArrayList:线程不安全,查询速度快,底层用的是数组,增删慢LinkedList:线程不安全,链表结构,增删速度快,查询慢Vect ...

  8. SQL结果统计 GROUP BY

    在结果几种,使用GROUP BY进行相同项求和的时候SELECT的字段要与GROUP BY后面的一一对应. select M.TIME,M.PRODUCTMODEL,M.PROCESS_PRODUCT ...

  9. 对html2canvas的研究

    介绍 该脚本允许您直接在用户浏览器上截取网页或部分网页的“屏幕截图”.屏幕截图基于DOM,因此它可能不是真实表示的100%准确,因为它没有制作实际的屏幕截图,而是根据页面上可用的信息构建屏幕截图. 这 ...

  10. 阿里云服务器 CentOS 7.5 64位 docker安装redis集群

    网上有很多教程可以参考,但是遇到坑了...... 最后参考这个教程成功了.https://www.cnblogs.com/hbbbs/articles/10028771.html 安装docker 参 ...