Flask+Vue 初試牛刀


------------------------------------------------------------------------------------------------------------------

工具:

pycharm

python

vscode

vue

-----------------------------------------------------------------------------------------------------------------

flask 環境准備:

 

一:python,pycharm 安裝, 已有不做介紹;

二:新建項目,並創建虛擬環境;

 

 

          解釋器選擇前面安裝的版本,項目路徑自己定義;

三:安裝flask;

 

 

 四:在項目路徑下新建 app.py文件,內容 如下:

 

 五:開啟測試服務器;

        打開command prompt,   cd 到app.py 文件所有文件夾,運行

                      set FLASK_APP=app.py

        再運行

                       python -m flask run

    就開啟了測試服務器http://127.0.0.1:5000

 

六:瀏覽器訪問 http://127.0.0.1:5000 ,可以訪問的話,說明flask工作正常;

 ——————————————————————————————————————————————————————————————

 

 

vue環境准備:

 

一: 后續准備采用 npm【Nodejs下的包管理器】的方式安裝vue,所以第一步安裝 node , 官網下載安裝即可;

     安裝完成之后在 command prompt  運行  node -v , 便可查看到安裝的nodejs 的版本,說明安裝成功;

      

 

     npm 是集成在node中的,也可以運行: npm -v 查看安裝的npm 版本:

       

二:安裝cnpm;

        命令行運行   npm install -g cnpm --registry=http://registry.npm.taobao.org  沒報錯的話表示安裝成功;

       

三:安裝vue-cli 腳手架構建工具

命令行運行    npm install -g vue-cli   然后等待安裝完成,

        安裝成功之后 運行    vue -v   可查看版本,版本出來的話說明安裝成功;

        

 

       

         命令行再運行  webpack -v 

         若提示webpack 不是內部命令,需要在cmd中運行 npm install webpack -g 安裝webpack;

 

四:命令行工具cd 要創建項目的文件夾路徑下,運行 vue creat myproject [myproject 為項目的文件夾名字] ,

        然后就會出現腳手架配置工具,初步配置如下:

       

 

 

五:命令行工具cd 到剛創建的 myproject 路徑下, 然后運行  npm run serve  即開始編譯;

 

六:完成之后瀏覽器訪問:http://127.0.0.1:8080/,便可以訪問項目默認的頁面:

       

 

 

  到此說明vue 環境准備完成;

——————————————————————————————————————————————————————————

嘗試用 vscode直接打開myproject文件夾:

                  

 

 主要嘗試說明src下面幾個文件和文件夾的作用:

 

 

下面單獨對每個文件嘗試理解一下:

App.vue 這個文件內容如下:

 

 

 從結構上來看,有兩部分內容,一部分是 <template>  ...  </template> , 這部分定義的渲染要用到的其他模塊和訪問路徑:

 

 

 主路徑下的Home, /about 路徑下 About 

對應顯示的頁面是這樣,根地址http://127.0.0.1:8080/顯示的Home的內容,http://127.0.0.1:8080/about 路徑顯示的 About的內容:

 

 

另外一部分是 <style> ...  </style>, 定義的主頁的css 樣式,

#app 定義的是   div id = app 結構的樣式,

#nav 定義的是   div id =  nav 結構的樣式

#nav a 定義的是有鏈接的文字樣式

#nav a.router-link-exact-active 定義的是鏈接激活之后的樣式

 

 

 

------------------------------------------------------------------------------------------------------------------------------

實際上我們看到的內容應該在views文件夾中,打開views文件,有Home.vue 和 About.vue 兩個模板:

 

 

 

 Home.vue 文件內容如下,還是由兩部分組成 <template> ...</template>  和 <script>  </script>  模板和js腳本兩部分; 

 

 

 

其中<template>...</template>  中home 類定義了兩個內容,一個是圖片,另一個是HelloWord 組件,

這個組件的提示信息通過 msg 顯示,另外的內容通過 <script> ... </script> 導入:

@表示的是/src 

 

 

 

下面看下 HelloWorld.vue, 還是由三部分組成,<template>  <script> <style> 

 

 

 模板定義的是HTML顯示的內容

 

 

 

About.vue 文件內容相對簡單,

 

 

 

————————————————————————————————————————————————————————————————

 

下面看下 router/index.js , 這個文件定義的是      模塊和URL映射

 

const routes 定義了 path ,name, component  , path是路由路徑,component 定義的是渲染模板,

模板可以通過例如: import Home from '../views/Home.vue' 的方式定義;

模板也可以通過例如:component: ()  => import (/* webpackChunkName: "about" */ '../views/About.vue')  的方式定義;

 

 

 ---------------------------------------------------------------------------------------------------------------------------------------------------

 

 

下面我們開始改造工作,把基礎的環境改成成我們想要的。

 

1:通過axios庫來連接Vue前端和Flask后端使用AJAX請求進行通信;

              命令行工具cd 到myproject 路徑,然后命令行運行: npm  install axios 

 

2:  對HelloWorld.vue 模板進行改造;

     script 中導入 axios , 同時增加空置的對象data ,  獲取的method:

     const path = http://localhost:5000/ 這個路徑為flask中app.py 定義的內容路由路徑;

     

 3.   pycharm  ,vscode 同時都保存文件,同時確保服務器在運行狀態。

      

 

 

      

 4.   訪問網址http://127.0.0.1:8080/, 在網址下看flask中定義的內容,說明連通成功,返回了flask 后台的內容;

       

       

 

 

 

 

 ---------------------------------------------------------------------------------------------------------------------------------------------

 

 

安裝Bootstrap 樣式

命令行工具運行  npm install bootstrap --save

client/src/main.js中引入Bootstrap

 

添加Bootstrap按鈕控件,測試一下效果;

 

 

 

 

下面嘗試做個改造例子,了解一下過程:

 1. 在components文件夾中添加一個新的模塊Books.vue

     

 

 

 

 2. 更新一下路由router/index.js將首頁/路由指向Books模塊

       

 

 

 3.  刷新http://127.0.0.1:8080/  可看到新的模板;

      

 

 

 4.  將Books.vue 里面的模板替換為Bootstrap風格表格

      

 

 

 5. 刷新http://127.0.0.1:8080/  可看到新的模板;

     

 

 

 6. 下面要實現的是 前端界面和后端的API進行交互

      RESTfu API規范的后端服務,使用HTTP中的GET,POST,PUT,DELETE方法進行通信

 

      Server端(Flask)設置

    1. app.py中添加一個存放圖書的數組變量模擬數據

      

 

 

      2. 修改Flask主文件app.py的路由

      

 

 

     3.  刷新http://127.0.0.1:5000/,可看到返回的json 話的數組數據;

        

 

Client端(VUE)設置

    1. 更新一下components/Books.vue模塊的script 

        

 

 

        備注:

        當Books.vue模塊created()完成的時候,調用getBooks()函數從后台獲取圖書數據
         模板部分使用了v-for標簽,在table中循環輸出行,將循環過程中的index作為了key主鍵(該主鍵設置是VUE規范推薦的,據說可以提高渲染效率). 使用v-if標簽來判斷渲染read是否的值.

     

        更新后的頁面如下:

        

 

 

        2. 使用Bootstrap中的模態框控件來實現添加新書的界面

                 1 . npm安裝bootstrap-vue包,命令行運行:npm install bootstrap-vue --save

                 2.  修改client/src/main.js啟用bootstrap-vue

                      

 

    POST路由設置

        1. 更新app.py處理添加新書時POST請求的路由,修改之前添加過的路由, methods增加POST類型,然后通過判斷request.method來確定接下來要進行的操作;

             

 

 

          2. 更新一下import部分的引入:  from flask import Flask, jsonify, request

           

Client端設置

       1. 在主<div>里面添加一個模態框來實現增加新圖書的界面

               

                 這里使用了v-model標簽來綁定input輸入框中的值和VUE中data數據對象中的addBookForm變量(這個變量在下面代碼中聲明)

       2.  更新下script部分的代碼

       3.  最終的Books.vue 的代碼如下:

             <template>

   < div  class= "container" >
     < div  class= "row" >
       < div  class= "col-sm-10" >
         < h1 >Books </ h1 >
         < hr / >
         < br / >
         < br / >
         < button  type= "button"  class= "btn btn-success btn-sm"  v-b-modal. book-modal >Add Book </ button >
         < br / >
         < br / >
         < table  class= "table table-hover" >
           < thead >
             < tr >
               < th  scope= "col" >Title </ th >
               < th  scope= "col" >Author </ th >
               < th  scope= "col" >Read? </ th >
               < th ></ th >
             </ tr >
           </ thead >
           < tbody >
             < tr  v-for="( bookindexin  books" : key=" index" >
               < td >{{  book. title }} </ td >
               < td >{{  book. author }} </ td >
               < td >
                 < span  v-if=" book. read" >Yes </ span >
                 < span  v-else >No </ span >
               </ td >
               < td >
                 < div  class= "btn-group"  role= "group" >
                   < button  type= "button"  class= "btn btn-warning btn-sm" >Update </ button >
                   < button  type= "button"  class= "btn btn-danger btn-sm ml-2" >Delete </ button >
                 </ div >
               </ td >
             </ tr >
           </ tbody >
         </ table >
       </ div >
     </ div >
     < b-modal  ref= "addBookModal"  id= "book-modal"  title= "Add a new book"  hide-footer >
       < b-form @ submit=" onSubmit" @ reset=" onResetclass= "w-100" >
         < b-form-group  id= "form-title-group"  label= "Title:"  label-for= "form-title-input" >
           < b-form-input
             id= "form-title-input"
             type= "text"
             v-model=" addBookForm. title"
             required
             placeholder= "Enter title"
           ></ b-form-input >
         </ b-form-group >
         < b-form-group  id= "form-author-group"  label= "Author:"  label-for= "form-author-input" >
           < b-form-input
             id= "form-author-input"
             type= "text"
             v-model=" addBookForm. author"
             required
             placeholder= "Enter author"
           ></ b-form-input >
         </ b-form-group >
         < b-form-group  id= "form-read-group" >
           < b-form-checkbox-group  v-model=" addBookForm. readid= "form-checks" >
             < b-form-checkbox  value= "true" >Read? </ b-form-checkbox >
           </ b-form-checkbox-group >
         </ b-form-group >
         < b-button-group >
           < b-button  type= "submit"  variant= "primary" >Submit </ b-button >
           < b-button  type= "reset"  variant= "danger" >Reset </ b-button >
         </ b-button-group >
       </ b-form >
     </ b-modal >
   </ div >
</ template >

< script >
import  axios  from  "axios";

export  default {
   data() {
     return {
       books: [],
       addBookForm: {
         title:  "",
         author:  "",
         read: []
      }
    };
  },
   methods: {
     getBooks() {
       const  path =  "http://localhost:5000/";
       axios
        . get( path)
        . then( res  => {
           this. books =  res. data. books;
        })
        . catch( error  => {
           // eslint-disable-next-line
           console. error( error);
        });
    },
     addBook( payload) {
       const  path =  "http://localhost:5000/";
       axios
        . post( pathpayload)
        . then(()  => {
           this. getBooks();
        })
        . catch( error  => {
           // eslint-disable-next-line
           console. log( error);
           this. getBooks();
        });
    },
     initForm() {
       this. addBookForm. title =  "";
       this. addBookForm. author =  "";
       this. addBookForm. read = [];
    },
     onSubmit( evt) {
       evt. preventDefault();
       this. $refs. addBookModal. hide();
       let  read =  false;
       if ( this. addBookForm. read[ 0])  read =  true;
       const  payload = {
         title:  this. addBookForm. title,
         author:  this. addBookForm. author,
         read  // property shorthand
      };
       this. addBook( payload);
       this. initForm();
    },
     onReset( evt) {
       evt. preventDefault();
       this. $refs. addBookModal. hide();
       this. initForm();
    }
  },
   created() {
     this. getBooks();
  }
};
</ script >

 

 

 

            代碼解釋一下:

                1data中新創建了一個addBookForm對象,用來和表單中的input控件使用v-model標簽進行數據雙向綁定(這正是VUE的魅力所在)

               2. onSubmit()函數和<b-form>中的submit屬性進行了綁定,用戶在提交表單的時候會調用.

                   其中evt.preventDefault()是用來屏蔽瀏覽器默認的提交表單操作,this.$refs.addBookModal.hide()用來關閉模態框,隨                 

                   后調用addBook()提交數據給后台添加新圖書,最后通過initForm()重置表單數據

                3. addBook()函數發送POST請求給后台的/books路徑用來添加新圖書;

 

          

Alert提醒模塊

       1.  添加一個用來反饋提醒用戶操作結果的模塊../src/components/Alert.vue

            

 

       2.  client/src/components/Books.vue模塊中修改script部分代碼注冊上面添加的Alert.vue模塊

             

 

 

        3. 刷新一下瀏覽器,可以看到Alert模塊引用並顯示成功

           

 

 

 

        4. Alert模塊使用b-alert標簽進行Bootstrap樣式改造

          <template>

   < div >
     < b-alert  variant= "success"  show >{{  message }} </ b-alert >
     < br >
   </ div >
</ template >

< script >
export  default {
   props: [ 'message'],
};
</ script >

          b-alert標簽中使用了variant來定義顏色樣式, show定義了顯示時候使用漸變動畫

          這里注意一下在script中使用了props來定義聲明模塊中所包含的屬性變量,

          這樣我們自定義的這個模塊就可以在被調用的時候,message會作為<alert></alert>標簽中的一個屬性 來接收參數.

 

       5.  回到Books模塊中,可以帶參數形式的調用Alert模塊了,例如這樣:

           <alert message="hi"></alert>

    6. 為了為了讓alert模塊中的message變量實現動態化,使用:變量名=語法進行數據雙向綁定

           <alert :message="message"></alert>

7. 在VUE的data變量中聲明message變量:

            

 

       8. 改造一下addBook()函數,加入對message變量的操作

              addBook(payload) {

        const  path =  'http://localhost:5000/';
        axios. post( pathpayload)
         . then(()  => {
           this. getBooks();
           this. message =  'Book added!';
        })
        . catch(( error=> {
           // eslint-disable-next-line
          console. log( error);
          this. getBooks();
     });
    },

      9. 使用v-if標簽,實現只有showMessage變量為真的時候才顯示Alert模塊

            <alert :message=message v-if="showMessage"></alert>>

      10. 需要在data中聲明這個showMessage變量,並且修改addBook()函數,加入對showMessage的操作

           

 

PUT路由設置

      1. 更新已有的數據需要添加唯一的id標識,可以使用Python標准庫中的uuid來生成

           修改server/app.pyBOOKS數組變量,別忘了引入uuid

         

 

       2. 修改路由中的all_books()函數,為新增加的書添加隨機的唯一id

        

 

       3.  增加一條新的路由,用來根據id查看單個書信息

       

 

      4. 再添加個刪除書操作的函數(內部調用的,不用關聯路由)

       

 

    

 

Client端設置

     實現修改書籍操作功能的待辦事項:

  1. 添加一個模態框表單
  2. 處理Update按鈕的點擊事件
  3. 通過AJAX發送請求
  4. 通知用戶操作結果處理取消按鈕的點擊事件

1.添加模態框表單

 

Books.vue模塊的template區域之前寫好的模態框后面再寫個模態框:

 

 

            

 

                      

    

 

 

 

 
< script >
import  axios  from  "axios";

export  default {
   data() {
     return {
       books: [],
       addBookForm: {
         title:  "",
         author:  "",
         read: []
      }
    };
  },
   methods: {
     getBooks() {
       const  path =  "http://localhost:5000/";
       axios
        . get( path)
        . then( res  => {
           this. books =  res. data. books;
        })
        . catch( error  => {
           // eslint-disable-next-line
           console. error( error);
        });
    },
     addBook( payload) {
       const  path =  "http://localhost:5000/";
       axios
        . post( pathpayload)
        . then(()  => {
           this. getBooks();
        })
        . catch( error  => {
           // eslint-disable-next-line
           console. log( error);
           this. getBooks();
        });
    },
     initForm() {
       this. addBookForm. title =  "";
       this. addBookForm. author =  "";
       this. addBookForm. read = [];
    },
     onSubmit( evt) {
       evt. preventDefault();
       this. $refs. addBookModal. hide();
       let  read =  false;
       if ( this. addBookForm. read[ 0])  read =  true;
       const  payload = {
         title:  this. addBookForm. title,
         author:  this. addBookForm. author,
         read  // property shorthand
      };
       this. addBook( payload);
       this. initForm();
    },
     onReset( evt) {
       evt. preventDefault();
       this. $refs. addBookModal. hide();
       this. initForm();
    }
  },
   created() {
     this. getBooks();
  }
};
</ script >


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM