zoukankan      html  css  js  c++  java
  • 测开之路一百四十:可拔插视图(基于类、基于方法)

    可拔插视图

    基于类的视图

    1、写类,继承flask.views.View
    2、实现方法,dipatch_request(self)
    3、app注册网址规则:
      1.导入视图类
      2.app.add_url_rule(地址, view_func=类名.as_view(终结点))

    新建一个html,为注册页

    新开一个路径,下面新建一个py文件用于存放类的视图

    """
    基于类的视图, 每一个视图写为一个类,用于做视图分类,如用户管理模块、业务处理模块
    dispatch_request:调度请求
    """
    from flask import render_template
    from flask.views import View


    class RegUser(View):
    """ 注册 """

    def dispatch_request(self):
    return render_template('reg.html')


    class UserLogin(View):
    """ 登录 """

    def dispatch_request(self):
    return render_template('login.html')

    为避免冲突,把main里面的login注释掉

    在main里面调用刚刚的类视图

    base.html加一个注册按钮,重定向到终结点为reg的视图

    <!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>
    <a href="{{ url_for('reg') }}">用户注册</a>
    </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>

    点用户注册,跳转到注册页面

    基于方法的视图

    1、写类,继承flask.views.MethodView
    2、实现方法
      GET: def get(self):
      POST:def post(self):
      PUT def put(self):
    3、app注册网址规则:
      1.导入视图类
      2.app.add_url_rule(地址, view_func=类名.as_view(终结点))

    from flask import render_template
    from flask.views import View, MethodView


    class ARegUser(MethodView):
    def get(self):
    """ get时的处理逻辑 """
    return render_template('reg.html')

    def post(self):
    """ post时的处理逻辑 """
    pass

    调用

    # 调用基于方法的视图
    from account.views import ARegUser
    app.add_url_rule('/reg/', view_func=ARegUser.as_view('reg'))

    views.py

    """
    基于类的视图, 每一个视图写为一个类,用于做视图分类,如用户管理模块、业务处理模块
    dispatch_request:调度请求
    """
    from flask import render_template
    from flask.views import View, MethodView


    class ARegUser(MethodView):
    def get(self):
    """ get时的处理逻辑 """
    return render_template('reg.html')

    def post(self):
    """ post时的处理逻辑 """
    pass


    class RegUser(View):
    """ 注册 """

    def dispatch_request(self):
    return render_template('reg.html')


    class UserLogin(View):
    """ 登录 """

    def dispatch_request(self):
    return render_template('login.html')

    main.py

    # coding:utf-8
    import sqlite3
    from datetime import datetime, timedelta
    from flask import Flask, request, render_template, redirect, url_for, g, send_from_directory, session, make_response

    app = Flask(__name__)

    DATABASE = r'.dbfeedbach.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视图来执行让页面跳转到登录页


    @app.route('/setck/')
    def setck():
    """ 添加cookie,timedelta由datatime导入 """
    response = make_response('ok')
    response.set_cookie('username', 'aaa', path='/', expires=datetime.now() + timedelta(days=7))
    # set_cookie 参数
    # dmain='baidu.com' 指定cookie只对baidu.com起作用
    # path='/' 此cookie能访问的路径
    # httponly=True 只能http访问,默认关闭
    # max_age=60 cookie生命周期,默认为None,浏览器关闭时销毁,单位为秒
    # expires=datetime.now() + timedelta(days=7) # 指定过期时间为7天
    return response


    @app.route('/getck/')
    def getck():
    """ 获取cookie request.cookies.get('xxx') """
    ck = request.cookies.get('username')
    if ck:
    return ck
    return '未获取到cookie'


    @app.route('/rmck/')
    def remove_cookie():
    """ 删除cookie,
    由于不允许直接操作硬盘,所以采用更新cookie生效时间的方法
    找到cookie,把生效时间设为当前时间之前
    """
    resp = make_response('删除cookie')
    # 把生效时间设为上一秒
    resp.set_cookie('username', '', expires=datetime.now() + timedelta(minutes=-1))
    return resp


    # 调用基于类的视图
    from account.views import RegUser, UserLogin

    # 为导入的基于类的视图添加分配url规则
    # 第一个参数:地址,第二个login为终结点,即视图函数名,可用于重定向
    # app.add_url_rule('/login/', view_func=UserLogin.as_view('login'))
    # app.add_url_rule('/reg/', view_func=RegUser.as_view('reg'))

    # 调用基于方法的视图
    from account.views import ARegUser
    app.add_url_rule('/login/', view_func=UserLogin.as_view('login'))
    app.add_url_rule('/reg/', view_func=ARegUser.as_view('reg'))


    if __name__ == '__main__':
    app.run(
    debug=True
    )
  • 相关阅读:
    Opencv算法运行时间
    markdown转换为html
    jQuery类名添加click方法
    box-sizing 盒子模型不改变大小
    nodejs 发送get 请求 获取博客园文章列表
    6、Python3中的常用正则表达式
    5、Python3打印函数名之__name__属性
    4、reduce函数工具的使用
    3、Python字符编码区分utf-8和utf-8-sig
    9、QT QLineEdit 密码模式
  • 原文地址:https://www.cnblogs.com/zhongyehai/p/11481975.html
Copyright © 2011-2022 走看看