測開之路一百四十:可拔插視圖(基於類、基於方法)

 

可拔插視圖css

 

基於類的視圖html

一、寫類,繼承flask.views.View
二、實現方法,dipatch_request(self)
三、app註冊網址規則:
  1.導入視圖類
  2.app.add_url_rule(地址, view_func=類名.as_view(終結點))前端

 

新建一個html,爲註冊頁jquery

 

 

新開一個路徑,下面新建一個py文件用於存放類的視圖sql

"""
基於類的視圖, 每個視圖寫爲一個類,用於作視圖分類,如用戶管理模塊、業務處理模塊
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裏面調用剛剛的類視圖flask

 

 

 

base.html加一個註冊按鈕,重定向到終結點爲reg的視圖bootstrap

 

<!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>

點用戶註冊,跳轉到註冊頁面瀏覽器

 

 

 

 

基於方法的視圖安全

一、寫類,繼承flask.views.MethodView
二、實現方法
  GET: def get(self):
  POST:def post(self):
  PUT def put(self):
三、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-8import sqlite3from datetime import datetime, timedeltafrom flask import Flask, request, render_template, redirect, url_for, g, send_from_directory, session, make_responseapp = 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 dbdef 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 osdef 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 ARegUserapp.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    )
相關文章
相關標籤/搜索