Flask操作

[TOC]

1. flask_login實現(xiàn)登錄功能

from flask import Flask, request, render_template, redirect, url_for
from flask_login import LoginManager, login_required, login_user, logout_user, UserMixin

# 程序?qū)嵗?app)是Flask對象域携,參數(shù)是程序主模塊的名字__name__
app = Flask(__name__)
# Login_Manager初始化與配置
login_manager = LoginManager()
login_manager.init_app(app)
# 設(shè)置密鑰值看锉,會用在表單提交等地方
app.config['SECRET_KEY'] = '234rsd12312sadfrwsf'

# 需要自定義用戶模型類
class User(UserMixin):
    pass
# 注冊用戶
users = [
    {'id': 1, 'username': 'v_jyzang', 'password': '123'},
    {'id': 2, 'username': 'yipingdeng', 'password': '123'},
]
# 從list(或者數(shù)據(jù)庫)中查詢id,返回對應(yīng)的用戶對象
def query_user(id):
    for user in users:
        if id == str(user['id']):
            return user

# 定義回調(diào)函數(shù)疼电,通過id返回用戶對象(flask_login必須要有這個方法)
@login_manager.user_loader
def load_user(id):
    if query_user(id) is not None:
        cur_user = User()
        # 動態(tài)語言界弧,可以動態(tài)增加新成員屬性
        cur_user.id = id
        return cur_user

@app.route('/tip')
@login_required
def tip():
    return render_template("index.html")

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        # request.args.get(key) 傳遞GET方法的參數(shù)
        # request凿跳。form.get(key) 傳遞POST方法的參數(shù)
        id = request.form.get('username')
        user = query_user(id)
        if user is not None and request.form['password']==user['password']:
            cur_user = User()
            cur_user.id = id
            # 調(diào)用login_user()方法良拼,傳入用戶對象
            login_user(cur_user)
            return redirect(url_for('tip'))

    return render_template("login.html")


@app.route('/logout')
@login_required
def logout():
    logout_user()


if __name__ == '__main__':
    app.run()

2. 前端分頁

參考:http://www.reibang.com/p/d45a470d2762

<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>Home</title>

    <link rel="stylesheet" >
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    {#<link rel="stylesheet" href="../static/assets/css/style.css">#}

    <script type="text/javascript">
        var nums=new Array(10);
        nums[0]="不是";
        nums[1]="是";
        nums[2]="不確定";

        //接收后端傳來的全部數(shù)據(jù)
        var result = eval('{{ result|safe }}');
        //組織表格數(shù)據(jù)
        var head = '<thead><tr>'+
            '<td>歌曲id</td>'+
            '<td>歌曲名</td>'+
            '<td>歌手名</td>'+
            '<td>候選Tip</td>'+
            '<td>點贊數(shù)</td>'+
            '<td>標(biāo)簽</td>'+
            '</tr></thead><tbody>';
        //表內(nèi)容
        var pageData=[];
        for(var i = 0; i < result.length; i++){
            var data = '<tr>'+
            '<td>'+result[i][1]+'</td>'+
            '<td>'+result[i][5]+'</td>'+
            '<td>'+result[i][6]+'</td>'+
            '<td>'+result[i][2]+'</td>'+
            '<td>'+result[i][3]+'</td>'+
            '<td>'+nums[result[i][4]]+'</td>'+
            '<td>'+
                '<form action="/select_tip" method="get">'+
                    '<input type="hidden" name="id" value="'+result[i][0]+'" >'+
                    '<input type="submit" name="tag" class="btn btn-sm btn-default" value="查看">'+
                '</form>'+
            '</td>'+
            '</tr>';
            pageData.push(data);
        }
        //表結(jié)尾
        var end='</tbody>';

        $(function(){
            var Count = pageData.length; //記錄條數(shù)
            var PageSize = 10; //設(shè)置每頁示數(shù)目
            var PageCount = Math.ceil(Count/PageSize); //計算總頁數(shù)
            var currentPage = 1; //當(dāng)前頁,默認(rèn)為1就斤。

            //分頁按鈕
            for(var i = 1; i <= PageCount; i++){
                var pageN='<a href="#" selectPage="'+i+'" >   '+i+'   </a>';
                $('#page').append(pageN);
            }

            //清空table悍募,默認(rèn)填充第一頁內(nèi)容
            $('#table').empty().append(head);
            for(i = (currentPage-1)*PageSize; i < PageSize*currentPage; i++){
                $('#table').append(pageData[i]);
            }
            $('#table').append(end);

            //顯示選擇頁的內(nèi)容
            $('a').click(function(){
                var selectPage = $(this).attr('selectPage');
                $('#no_page').html(selectPage);
                //清空table,重新填充
                $('#table').html('');
                $('#table').append(head);
                for(i = (selectPage-1)*PageSize; i < PageSize*selectPage; i++){
                    $('#table').append(pageData[i]);
                }
                $('#table').append(end);
            });
        });
    </script>
</head>
<body>
    <div class="wrapper">
        <div class="form-top1"> <!--底框-->
            <h3 class="text-center">Home</h3>
            <table class="table table-bordered" id="table" border="1">

            </table>
            <span id="no_page"></span>
            <div id="page" style="width:450px;margin:0 auto;">頁數(shù)</div>
        </div>
    </div>
</body>
</html>
image.png

3. ajax異步提交洋机,當(dāng)前頁面響應(yīng)

javascript

<script>
        function add_ajax(i) {
            $.ajax({
                url: '/mark',
                type: 'GET',
                data: $('#mark'+i).serialize(), //序列化為鍵值對
                success: function (data) { // 返回2XX響應(yīng)后觸發(fā)的回調(diào)函數(shù)
                    $('#mark'+i).append(data); // 將返回的響應(yīng)插入到頁面中
                },
                error: function (data) {
                    $('#mark'+i).append("Error");
                }
            });
            //響應(yīng)信息在當(dāng)前頁面插入坠宴,而不是另起頁面顯示
            return false;
        }
</script>

html

<html>
    //傳給后端做處理,后端傳遞返回值給success字段
    {% for i in range(3) %}
        <form id="mark{{ i }}" onsubmit="return add_ajax({{ i }})">
            <input type="hidden"  name="mark_id" value="sbasa">
            <input type="submit" id="biaoji{{ i }}" value="標(biāo)記">
        </form>
    {% endfor %}
</html>
image.png

jquery其他事件綁定:

eg. 
//放在回調(diào)函數(shù)里绷旗,防止頁面還沒有加載好的時候就運行jquery
$(function(){
    $('form').submit(function(){...});
});
blur() 元素失去焦點
focus() 元素獲得焦點
click() 鼠標(biāo)單擊
mouseover() 鼠標(biāo)進入(進入子元素也觸發(fā))
mouseout() 鼠標(biāo)離開(離開子元素也觸發(fā))
mouseenter() 鼠標(biāo)進入(進入子元素不觸發(fā))
mouseleave() 鼠標(biāo)離開(離開子元素不觸發(fā))
hover() 同時為mouseenter和mouseleave事件指定處理函數(shù)
ready() DOM加載完成
resize() 瀏覽器窗口的大小發(fā)生改變
scroll() 滾動條的位置發(fā)生變化
submit() 用戶遞交表單

4. 后端分頁

參考:https://www.cnblogs.com/wuxie1989/p/7027843.html
http://www.manongjc.com/detail/13-kxskdzykqjfjnws.html

#定義Pager類
class Pager:
    def __init__(self, data, page_size):
        self.data = data  # 總數(shù)據(jù)
        self.page_size = page_size  # 單頁大小
        self.is_start = False
        self.is_end = False
        self.data_count = len(data)
        self.next_page = 0  # 下一頁
        self.previous_page = 0  # 上一頁
        self.page_num = self.data_count / page_size  # 總頁數(shù)
        if self.page_num == int(self.page_num):
            self.page_num = int(self.page_num)
        else:
            self.page_num = int(self.page_num) + 1

    def page_data(self, page):
        """
        獲取一頁的數(shù)據(jù)
        :param page: 要返回數(shù)據(jù)的頁碼
        :return: 如果頁碼超過總頁碼喜鼓,返回空列表,否則返回一頁的數(shù)據(jù)
        """
        print(page, self.page_num)
        if page > self.page_num:
            return []
        self.next_page = page + 1
        self.previous_page = page - 1
        if page == 1:
            self.is_start = True
        elif page == self.page_num:
            self.is_end = True
        if self.is_end:
            return self.data[(page - 1) * self.page_size:]
        else:
            return self.data[(page - 1) * self.page_size:page * self.page_size]

法一:在不刷新頁面的前提下翻頁衔肢,利用ajax提交翻頁請求(瀏覽器url不變庄岖,不顯示page),success回調(diào)函數(shù)中清除table信息角骤,重新填充下一頁信息隅忿。
缺點:刷新之后會返回第一頁,不會留在當(dāng)前頁邦尊;如果在某一頁點擊詳情進入新頁面背桐,回退之后也只會回到第一頁

<button type="button" class = "pagebtn" onclick="next_page(-1)">上一頁</button>
<span id ="page_display" style="display: inline">當(dāng)前頁1/{{page_num}}</span>
<button type="button" class = "pagebtn" onclick="next_page(1)">下一頁</button>
<script>
    cur_page = 1; // 當(dāng)前頁面號會隨頁面變化而變化
    傳值都是string要轉(zhuǎn)Int!2踝帷链峭!
    table_length = parseInt("{{ page_num }}"); //js中引用jinja2的變量要用雙引號括起來
    //翻頁函數(shù)
    // 參數(shù):當(dāng)前頁號,總頁數(shù)又沾,向前/后一頁
    function next_page(offset){
        cur_page = cur_page + offset; //翻頁
        //越界
        if (cur_page < 1){
            cur_page = 1;
        }
        else if (cur_page > table_length){
            cur_page = table_length;
        }

        if(cur_page <= table_length && cur_page >= 1){
            //創(chuàng)建表單
            var formData = new FormData();
            formData.append("cur_page", cur_page);
            //ajax提交表單
            $.ajax({
                url: '/page',
                type: 'POST', //用GET不行弊仪,不明
                data: formData,
                success: function (data) { // 返回2XX響應(yīng)后觸發(fā)的回調(diào)函數(shù)
                    $('#table').empty();
                    // 將json數(shù)據(jù)轉(zhuǎn)為JavaScript對象
                    var dict_data = $.parseJSON(data);

                    var pageData=[];
                    for(var i = 1; i < dict_data.page_data.length; i++) {
                        var data = '<tr>' +
                            '<td>' + dict_data.page_data[i][1] + '</td>' +
                            '<td>' + dict_data.page_data[i][5] + '</td>' +
                            '<td>' + dict_data.page_data[i][6] + '</td>' +
                            '<td>' + dict_data.page_data[i][2] + '</td>' +
                            '<td>' + dict_data.page_data[i][3] + '</td>' +
                            '<td>' + dict_data.page_data[i][4] + '</td></tr>';
                        pageData.push(data)
                    }
                    $('#table').append(pageData)
                    $('#page_display').html('當(dāng)前頁' + dict_data.cur_page + '/' + dict_data.page_num)

                },
                error: function (data) {},
                //傳遞FormData時需要這兩行
                processData: false,
                contentType: false
            });
        }
    }
</script>
@app.route('/page', methods=["GET", "POST"])
@login_required
def page():
    cur_page = int(request.form.get("cur_page"))
    ....查詢?nèi)拷Y(jié)果
    pager = Pager(result, page_size=10)
    return json.dumps({"page_data": pager.page_data(cur_page),
            "page_num": pager.page_num,
            "cur_page": cur_page})

法二:改進法一的缺點,讓瀏覽器url記錄頁碼信息(好像也可以用cookie做)這樣回退或刷新不會永遠在第一頁

<button type="button" class = "pagebtn" onclick="next_page(-1)">上一頁</button>
<span id ="page_display" style="display: inline">當(dāng)前頁{{ cur_page }}/{{ page_num }}</span>
<button type="button" class = "pagebtn" onclick="next_page(1)">下一頁</button>
<script>
    cur_page = parseInt("{{ cur_page }}");
    page_num = parseInt("{{ page_num }}"); //js中引用jinja2的變量要用雙引號括起來
    //翻頁函數(shù)
    // 參數(shù):當(dāng)前頁號捍掺,總頁數(shù)撼短,向前/后一頁
    function next_page(offset){
        cur_page = cur_page + offset; //翻頁
        //越界
        if (cur_page < 1){
            cur_page = 1;
        }
        else if (cur_page > page_num){
            cur_page = page_num;
        }
        console.log(cur_page);
        if(cur_page <= page_num && cur_page >= 1){
            // jquery創(chuàng)建表單
            var form = $('<form></form>')
            form.attr('action', '/panel');
            form.attr('method', 'get');
            var my_input = $('<input type="hidden" name="cur_page" />');
            my_input.attr('value', cur_page);

            form.append(my_input);
            $("body").append(form);
            form.submit(); //此法提交,瀏覽器url會記錄
        }
    }
</script>
后端直接使用原panel()函數(shù)挺勿,不用新增page()函數(shù)
@app.route('/panel', methods=["GET", "POST"])
@login_required
def panel():
    cur_page = request.args.get('cur_page')
    cur_page = int(cur_page) if cur_page else 1
    ····查詢?nèi)拷Y(jié)果
    pager = Pager(result, page_size=PAGE_SIZE)
    return render_template('panel.html',
                           username=current_user.username,
                           page_data = pager.page_data(cur_page),
                           page_num = pager.page_num,
                           cur_page = cur_page)

image.png

要做出詳細頁碼參考:https://www.cnblogs.com/w-yong/p/6255444.html

5. Bootstrap進度條

https://www.cnblogs.com/accordion/p/7764460.html
后端運行模型,運行結(jié)束后頁面跳轉(zhuǎn)喂柒,運行期間用進度條撐著

// EventSource實時通信不瓶,服務(wù)端向客戶端推送信息禾嫉,客戶端無需發(fā)送請求
    <script>
        var source = new EventSource("/progress");
        source.onmessage = function (event) {
            $('.progress-bar').css('width', event.data + '%').attr('aria-valuenow', event.data);
            $('.progress-bar-label').text(event.data + '%');
            if (event.data === '100') { // 到100斷開連接 
                source.close()
            }
        }
        
        function showbar() {
            $('.progress').css('display', 'block');
        }
    </script>
// 點擊事件發(fā)生,顯示進度條蚊丐,提交表單
<form ...action='/panel'>
    <button type="button" class = "pagebtn" onclick="showbar()">下一頁</button>
</form ...>
// 進度條模塊熙参,需引入bootstrap
<div class="progress" style="margin: 50px; display: none">
    <div class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="0"
                 aria-valuemin="0"
                 aria-valuemax="100" style="width: 0%">
        <span class="progress-bar-label">0%</span>
    </div>
</div>
// progress函數(shù)傳遞信號,通過全局變量progress_percentage反饋給前端
from flask import Response
@app.route('/progress')
def progress():
    def generate():
        global progress_percentage
        //兩個換行符表示當(dāng)前消息發(fā)送完畢
        return "data:" + str(progress_percentage) + "\n\n"
    //事件流對應(yīng)的MIME格式
    return Response(generate(), mimetype='text/event-stream')
//全局變量progress_percentage控制進度
progress_percentage=0
def panel():
    ...
    global progress_percentage
    time.sleep(5) // model1
    progress_percentage += 50
    time.sleep(5) //model2
    progress_percentage += 50
    ....
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末麦备,一起剝皮案震驚了整個濱河市孽椰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凛篙,老刑警劉巖黍匾,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異呛梆,居然都是意外死亡锐涯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門填物,熙熙樓的掌柜王于貴愁眉苦臉地迎上來纹腌,“玉大人,你說我怎么就攤上這事滞磺∩恚” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵击困,是天一觀的道長涎劈。 經(jīng)常有香客問我,道長沛励,這世上最難降的妖魔是什么责语? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮目派,結(jié)果婚禮上坤候,老公的妹妹穿的比我還像新娘。我一直安慰自己企蹭,他們只是感情好白筹,可當(dāng)我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著谅摄,像睡著了一般徒河。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上送漠,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天顽照,我揣著相機與錄音,去河邊找鬼。 笑死代兵,一個胖子當(dāng)著我的面吹牛尼酿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播植影,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼裳擎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了思币?” 一聲冷哼從身側(cè)響起鹿响,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谷饿,沒想到半個月后惶我,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡各墨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年指孤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贬堵。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡恃轩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出黎做,到底是詐尸還是另有隱情叉跛,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布蒸殿,位于F島的核電站筷厘,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏宏所。R本人自食惡果不足惜酥艳,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爬骤。 院中可真熱鬧充石,春花似錦、人聲如沸霞玄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坷剧。三九已至惰爬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惫企,已是汗流浹背撕瞧。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人风范。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓咨跌,卻偏偏與公主長得像沪么,于是被迫代替她去往敵國和親硼婿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容

  • Flask CookiesCookie以文本文件的形式存儲在客戶端的計算機上禽车。其目的是記住和跟蹤與客戶使用相關(guān)的數(shù)...
    菜鳥筆記閱讀 406評論 0 0
  • flask 運行流程 creat一個app對象,通過Flask(name)來注冊方法,然后run_app 通過fl...
    Colaplusice閱讀 1,219評論 0 0
  • 如何使用flask做vue的靜態(tài)文件服務(wù)器? 原理: 讓flask的靜態(tài)文件與模板文件的根目錄指向vue的靜態(tài)文件...
    唯此閱讀 2,502評論 0 0
  • 用戶認(rèn)證的原理在了解使用Flask來實現(xiàn)用戶認(rèn)證之前寇漫,我們首先要明白用戶認(rèn)證的原理。假設(shè)現(xiàn)在我們要自己去實現(xiàn)用戶認(rèn)...
    SkTj閱讀 1,936評論 0 6
  • 1殉摔,安裝flask_login pip install flask_login 2,在flask項目中配置flas...
    SkTj閱讀 611評論 0 0