Flask + vue 先後端分離的 二手書App

一個Flask + vue 先後端分離的 二手書App

效果展現:
https://blog.csdn.net/qq_42239520/article/details/88534955html

所用技術清單
在這裏插入圖片描述
項目地址:項目地址
vue代碼地址:vue代碼地址前端

項目部分過程筆記:vue

後臺:

項目結構ios

Secondhanbook /   項目目錄
    apps 
        v1
            __init__.py 導入 urls
            urls.py  路由配置
            forms.py
            models.py
            views
                user_views.py  用戶相關視圖
                book_vews.py 書籍相關視圖
    config.py  配置文件
    run.py  項目啓動文件
    manage.py  數據庫遷移文件
    Secondhanbook.py  初始化文件 
    utils  工具類目錄
        ......
    ......

1. Flask_RESTful 的返回 和 緩存時候的自定義返回git

flask_restful 在視圖方法上加上marshal_with 裝飾器,並傳遞你返回的模式。但當自定義時,須要返回本身的模式github

return marshal(books,self.resource_fields,envelope='data')
    resource_fields:自定義返回模式
    data:  返回時,數據包裝

2. 使用Flask_RESTful 下表單驗證以及csrf防護redis

每當用戶進入提交Post請求的頁面,實例化一個表單form,返回csrf_tokenvuex

csrf_token = form.csrf_token.current_token
 return restful.success(data=csrf_token)

3.路由配置數據庫

api = Api(prefix='/api')
#用戶相關
api.add_resource(Login,'/login/',endpoint='login')  
......
#書籍相關
api.add_resource(BookAddView,'/bookadd/',endpoint='bookadd')
......

4.使用itsdangerous生成臨時身份令牌
生成令牌json

def generate_auth_token(self,expiration=172800):#兩天過時
        s = Serializer(config.BaseConfig.SECRET_KEY,expires_in=expiration)
        return s.dumps({'id':self.id})

身份檢驗

def verify_auth_token(token):
        s = Serializer(config.BaseConfig.SECRET_KEY)
        try:
            data = s.loads(token)
        except Exception as e:
            return None
        user = FrontUserModel.query.get(data['id'])
        return user

5.配置文件的書寫方式,類繼承的方式

class BaseConfig(object):
    pass
class DevelopmentConfig(BaseConfig):
    pass
class OnlineConfig(BaseConfig):
    pass

6. celery 處理費時任務

@celery.task
def send_mail(subject,recipients,user_id):
   ......
@celery.task
def BookCacheAdd(books):
    ......

7.redis 存儲數據bytes 問題解決

cache = redis.StrictRedis(host='127.0.0.1',port=6379,db=0,decode_responses=True)

8. 封裝jsonfy的返回

class HttpCode(object):
    Ok = 200
    ParamerError = 400
    Unauth = 401
    ServerError = 500
def RestfulResult(code,message,data):
    return jsonify({'code':code,'message':message,'data':data})
def success(message="",data=None):
    return RestfulResult(HttpCode.Ok,message=message,data=data)
......

9.對axios 提交bytes類型數據進行form驗證

from werkzeug.datastructures import MultiDict
 ......
 myform = json.loads((request.data.decode('utf-8')))
 form = LoginForm(MultiDict(myform))
 ......

10. flask 接收 接收多個文件axios 上傳的多個文件

**  AddBookView  ** 
 files = request.files
 for file in files.values():
     filename = upload.change_filename(secure_filename(file.filename))
     
**upload.vue**
      for (var i = 0; i < this.files.length; i++) {
        this.formdata.append('file' + i, this.files[i])
      }
      axios.post('api/bookadd/', this.formdata, {
        headers: {'Content-Type': 'multipart/form-data'}
      }).then(this.handleAxiosDone)

11.表單對files, 輸入字段驗證

from werkzeug.datastructures import CombinedMultiDict
form = Yourform(CombinedMultiDict([request.form,   request.files])) //  合併 數據和文件
文件驗證:
定義表單時,採用FileField這個類型
驗證器導入:flask_wtf.file   
flask_wtf.file.FileRequired 驗證是否爲空
flask_wtf.file.FileAllowed 驗證上傳文件後綴名

前臺部分知識點:

項目結構

......
src
    common
        footer  頁腳
        alert    提示
        fade        動畫
        gallary  畫廊
        ......
    store
        ... vuex相關  
    pages
        home
            components
                header.vue
                ......
            Home.vue
        detail
        me
        sign
        ......
......

1. flask_result 返回時,提供默認值
返回數據時,當axios 未返回渲染到頁面時,使用變量出錯。
**** 解決方法: 定義默認值 例若有使用book.owner.username , book.owner.avatar時,不然報錯無定義,並沒有法顯示。

book: {
        owner: {......Object}
      },

2. vuex store一個Message,供於消息提醒
項目基本上每一個頁面都有操做結果的提醒,封裝一個消息提醒的組件 alert.vue

<div v-show="isshow" class="alertBox" :style="{background:this.$store.state.color}">
    {{mymessage}}
  </div>
......
  computed: {
    mymessage () {
      return this.$store.state.message
    }
  },
  watch: {
    mymessage (e) {
      this.isshow = true
    }
  }
state: {
    message: '默認值',
    color: ''
  },
  mutations: {
    msgchange (state, res) {
      state.message = res.message    // color 自定義消息
      state.color = res.color  // color 自定義顏色
      setTimeout(() => {
        state.message = ''
        state.color = ''
      }, 3000)
    }
  }
  
**** 重點:必須重置,不然下一次同樣的消息將不顯示

組件寫一個發送提醒消息的方法,方便屢次調用
handleemit (message, color) {
  this.$store.commit('msgchange', {message: message, color: color})
}

3. 登錄註冊:
利用 vue mounted 生命週期函數請求後端返回的csrf_token , 以及檢驗本地 localStorage,token是否過時。首次登錄成功返回存儲token

localStorage.setExpire('token', res.headers.token, 1000 * 60 * 60 * 24 * 2) // 設置兩天過時
 註冊發送email 激活帳號

4 . 使用better-scroll 加載更多
swiper 盒子必須小於content高度才能滾動

能夠滾動後,頁面將不能點擊,解決:****    
this.scroll = new BScroll(this.$refs.wrapper, {
      click: true,
      ......
監聽下拉方法,加載更多
    pullUpLoad: {
      // 當上拉距離超過盒子高度的的時候,就派發一個上拉加載的事件(觸發條件)
      threshold: 0
    }
監聽事件
   this.scroll.on('pullingUp', () => {
     axios.get('/api/booklist/?start=' + this.start).then(this.handleAxiosSuccess)
   })
   
*** 對於下拉加載更多,雙重遍歷,遍歷頁碼對應的數據
v-for="(p,index) in page" 
        v-for="item in booklist[index]" :key="item.id"   //  booklist[index] 爲第幾回下拉的返回的數據

5. vue-awesome-swiper

圖片點擊事件
監聽事件:
 on: {
   click: function (e) {
     window.open(e.target.src) // 跳轉到網頁
   }
 }
 使用:
 <swiper :options="swiperOption">  swiperOption爲參數{ loop: true,effect: 'fade'......}
   <!-- slides -->
   <swiper-slide v-for ='item of swiperList' :key="item.id">
     <img class="swiper-img" :src="item.url" alt=""> // 傳遞圖片url
   </swiper-slide>
 </swiper>

畫廊 組件關鍵參數:
 // observer啓動動態檢查器(OB/觀衆/觀看者),當改變swiper的樣式(例如隱藏/顯示)或者修改swiper的子元素時,自動初始化swiper。
  // 默認false
  observer: true,
  observeParents: true

6. 過濾器,傳遞data中的值,而且使用v-html 顯示

v-html="$options.filters.filemotion(comment.content,emotions)"  //       emotions: [] 是data中自定義的值
本過濾器是對,表情的插入表情標籤的過濾 [贊]  [哈哈]  替換成 圖片
方法:
emotions格式 :  
 filemotion (value, emotions) {
   value = value.replace(/(\[.+?\])/g, (e, e1) => {
     for (var i in emotions) {
       if ((emotions[i].value.indexOf(e1)) > -1) {
         return '<img src="' + emotions[i].icon + '">'
       }
     }
   })
   return value
 }

7. axios 更改請求頭:

axios.post('/api/comment/',參數, {
   headers: {
  'Content-Type': 'application/json'
    ......
   }
 })

8. Proxytable設置跨域,進行數據交互

proxyTable: {
      '/api': {
        target: 'http://127.0.0.1:5000',  //目標接口域名
        changeOrigin: true,  //是否跨域
        pathRewrite: {
          '^/api': '/v1/api/'   //重寫接口
        }
      }
    }

9.router 模式
路由 mode="history"模式
當前端項目結合到flask 項目中,當vue 路由爲history模式時,出現「刷新頁面報錯404」的問題

這是由於這是單頁應用…實際上是由於調用了history.pushState API 因此全部的跳轉之類的操做
都是經過router來實現的,解決這個問題很簡單,只須要在後臺配置若是URL匹配不到任何靜態資源

進入新頁面,不回到頁面頂部解決:

scrollBehavior (to, from, savedPosition) {
    return { x: 0, y: 0 }
  },
相關文章
相關標籤/搜索