Vue+Django+DRF項目搭建案例


1. Vue+Django+DRF項目搭建案例

1.1 企業的web項目類型

  1. 商城

    1.1 B2C 直銷商城 商家與會員直接交易 ( Business To Customer )

    1.2 B2B 批發商城 商家與商家直接交易

    1.3 B2B2C 購物平台 商家和會員在另一個商家提供的平台上面進行交易

    1.4 C2B 定制商城 會員向商家發起定制商品的需求,商家去完成。

    1.5 O2O 線上線下交易平台

    1.6 C2C 二手交易平台

  2. 門戶網站[企業站和門戶站]

  3. 社交網絡

  4. 資訊論壇

  5. 內部系統

  6. 個人博客

  7. 內容收費站

1.2 企業項目開發流程

開發流程

img

1.3 立項申請階段

立項其實就是對產品項目能不能做和怎么做,提出理論基礎。大的互聯網公司都有比較正規的立項流程。

20180601170947776

通常公司內部要研發一款軟硬件的產品之前,都要經過市場評估和調研分析,產生一份產品項目立項報告給公司。

產品項目立項報告一般包含以下內容:

項目概述
需求市場
需求分析和項目建設的必要性
業務分析
總體建設方案
項目風險和風險管理
可行性分析階段

參考資料:https://blog.csdn.net/m0_37370820/article/details/81077886

2. 需求分析

2.1 首頁

功能:導航菜單、輪播圖、退出登錄

1555309744206

2.2 登錄注冊

功能:用戶登錄、極驗驗證碼、多條件登錄、記住密碼、短信發送、短信冷卻倒計時、jwt認證

1555309859755

1555310015496

2.3 課程列表

功能:課程分類、課程列表、課程多條件篩選展示、課程分類展示、課程分頁展示、課程章節課時展示、課程優惠策略

1555311221819

2.4 課程詳情

功能:課程信息展示、視頻播放、富文本編輯器

1555311433851

2.5 購物車

功能:購物車商品列表、添加商品、刪除商品、勾選商品狀態、商品結算、訂單生成、唯一訂單號生成

1555311588633

2.6 商品結算

功能:訂單商品信息列表、訂單信息展示、積分計算功能、優惠券策略、課程有效期計算、第三方支付平台接口

1555311715736

2.7 購買成功

1553138273460

2.8 個人中心

功能列表:我的訂單、訂單狀態改變

1555312510196

2.9 視頻播放

功能:視頻加密播放

1553137882937

3. 環境搭建

3.1 創建虛擬環境

mkvirtualenv luffy

如果自己的開發機子中存在多個版本的python,則可以指定解析器的版本

mkvirtualenv luffy -p python3

1557367438248

3.2 相關命令復習

創建虛擬環境:               mkvirtualenv 虛擬環境名稱
創建虛擬環境(指定python版本): mkvirtualenv -p python3 虛擬環境名稱
查看所有虛擬環境:            workon+2次tab鍵
使用虛擬環境:               workon 虛擬環境名稱
退出虛擬環境:               deactivate
刪除虛擬環境(必須先退出虛擬環境內部才能刪除當前虛擬環境):
                           	rmvirtualenv 虛擬環境名稱
    
其他相關命令:
查看虛擬環境中安裝的包:              pip freeze  或者 pip list
收集當前環境中安裝的包及其版本:       pip freeze > requirements.txt
在部署項目的服務器中安裝項目使用的模塊: pip install -r requirements.txt

提示:

  • 虛擬環境只會管理環境內部的模塊和python解析器,對於源代碼是毫無關系

  • 創建虛擬環境需要聯網

  • 創建成功后, 會自動工作在這個虛擬環境上

  • 工作在虛擬環境上, 提示符最前面會出現 “(虛擬環境名稱)”

3.3 依賴包安裝

pip install django

pip install djangorestframework

pip install PymySQL

pip install Pillow

pip install django-redis

4. 搭建項目

4.1 創建項目

django-admin startproject luffy

效果:

1557367703530

4.3 打開項目

在pycharm中打開項目

1557367755691

設置虛擬環境

1553139497155

1557367856794

啟動django項目

use the manage.py not pycharm default start button

1557367925009

效果:

1557367991756

提示:

在pycharm中如果要使用已經創建好的虛擬環境,則必須設置pycharm中的python解釋器,設置為虛擬環境中的python。

4.2 調整目錄

├── docs/          # 項目相關資料保存目錄
├── logs/          # 項目運行時/開發時日志目錄
├── manage.py
├── luffy/         # 項目主應用,開發時的代碼保存
│   ├── apps/      # 開發者的代碼保存目錄,以模塊[子應用]為目錄保存
│   ├── libs/      # 第三方類庫的保存目錄[第三方組件、模塊]
│   ├── settings/
│       ├── dev.py   # 項目開發時的本地配置
│       ├── prop.py  # 項目上線時的運行配置
│   ├── urls.py    # 總路由
│   ├── utils/     # 多個模塊[子應用]的公共函數類庫[自己開發的組件]
└── scripts/       # 保存項目運營時的腳本文件

1557368526149

4.2.1 分不同環境進行項目配置

開發者本地的環境、目錄、數據庫密碼和線上的服務器都會不一樣,所以我們的配置文件可以針對不同的系統分成多分.

  1. 在項目主應用下,創建一個settings的配置文件存儲目錄
  2. 根據線上線下兩種情況分別創建2個配置文件 dev.py和prod.py
  3. 把原來項目主應用的 settings.py配置內容復制2份到dev.py和prod.py里面
  4. 把原來的settings.py配置文件修改文件名或者刪除

新的目錄settings:

1557368720318

接下來,就可以根據在manage.py中根據不同的情況導入對應的配置文件了.

1557368958823

4.3 創建代碼版本

cd進入到自己希望存儲代碼的目錄路徑,並創建本地倉庫.git【pycharm直接打開終端就是項目根目錄了。無須cd了】
新創建的本地倉庫.git是個空倉庫

cd 目錄路徑
git init

4.3.1 配置用戶名和郵箱

git config --global user.name 'lisi'
git config --global user.email 'lisi@163.com'

4.4 在git平台創建工程

公司一般都會有自己的代碼倉庫,一般都是自己搭建,也有使用第三方提供代碼管理平台。

常用的代碼管理平台:github、gitee(碼雲)

如果公司自己搭建的代碼管理平台,gitlab框架

1) 創建私有項目庫

1557373432053

1557373444325

創建私有空倉庫以后的界面:

1557373625527

1557373639755

2)克隆項目到本地

注意:
	我們當前項目不需要這個步驟
    這個步驟是 當以后我們進入公司里面,參與人家已經在做的項目時,別人已經有倉庫了,但是我們是新人加入項目中的,那么我們不需要在自己本地進行git init,直接git clone 復制別人的倉庫代碼
git clone 倉庫地址
注意,如果當前目錄下出現git倉庫同名目錄時,會克隆失敗。

1557373835075

3)創建並切換分支到dev

# git branch dev      # 創建本地分支dev,dev是自定義
# git checkout dev    # 切換本地分支代碼
git checkout -b dev   # 這里是上面兩句代碼的簡寫

git提交

git add 代碼目錄   # 添加代碼到上傳隊列
git status        # 查看當前項目的版本狀態
git commit -m '添加項目代碼'  # 提交代碼到本地倉庫, -m 表示本次提交的描述

推送到遠端

git push origin dev:dev

如果推送代碼,出現以下提示: git pull ....,則表示當前本地的代碼和線上的代碼版本不同.

1. 把線上的代碼執行以下命令,拉取到本地,進行同步
git pull

2. 根據提示,移除多余的沖突的文件,也可以刪除.
完成這些步驟以后,再次add,commit,push即可.

接下來,我們就把上面創建好的本地項目提交到gitee碼雲上面

# .表示當前目錄下所有的文件或目錄提交到上傳隊列[上傳隊列也叫"暫存區"]
git add .

# 把本地上傳隊列的代碼提交到本地倉庫
git commit -m "項目初始化搭建"

# 給本地的git版本控制軟件設置項目的遠程倉庫地址
git remote add origin https://gitee.com/mooluo/luffyproject.git

# 提交代碼給遠程倉庫
git push -u origin master
擴展:
1. 通過 git status 可以查看當前項目的代碼版本狀態
2. 通過 git reflog 可以查看代碼版本日志[簡單格式]
3. 通過 git log    可以查看代碼版本日志[詳細格式]

最終,成功提交了代碼版本到gitee平台。效果:

1557374414461

上面雖然成功移交了代碼版本,但是一些不需要的文件也被提交上去了。

所以,我們針對一些不需要的文件,可以選擇從代碼版本中刪除,並且使用.gitignore把這些垃圾文件過濾掉。

git rm 文件  # 刪除單個文件
git rm -rf 目錄  # 遞歸刪除目錄

# 以下操作建議通過ubuntu的終端來完成,不要使用pycharm提供,否則刪除.idea還會繼續生成。
git rm -rf .idea
git rm db.sqlite3
# 注意,上面的操作只是從項目的源代碼中刪除,但是git是不知情的,所以我們需要同步。
git add .
git commit -m "刪除不必要的文件或目錄"
git push -u origin master

使用.gitignore把一些垃圾文件過濾掉。

vim .gitignore

./idea
./idea/*
./git
./db.sqlite3

開發時我們經常會使用pycharm的提供的git管理工具來完成代碼的拉取和推送。

1557375896356

4.5 日志配置

在settings/dev.py文件中追加如下配置:

# 日志配置
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
        },
    },
    'filters': {
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'file': {
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',
            # 日志位置,日志文件名,日志保存目錄必須手動創建
            'filename': os.path.join(os.path.dirname(BASE_DIR), "logs/luffy.log"),
            # 日志文件的最大值,這里我們設置300M
            'maxBytes': 300 * 1024 * 1024,
            # 日志文件的數量,設置最大日志數量為10
            'backupCount': 10,
            # 日志格式:詳細格式
            'formatter': 'verbose'
        },
    },
    # 日志對象
    'loggers': {
        'luffy': {
            'handlers': ['console', 'file'],
            'propagate': True, # 是否讓日志信息繼續冒泡給其他的日志處理系統
        },
    }
}

4.6 異常處理

新建utils/exceptions.py

from rest_framework.views import exception_handler

from django.db import DatabaseError
from rest_framework.response import Response
from rest_framework import status

import logging
logger = logging.getLogger('luffy')


def custom_exception_handler(exc, context):
    """
    自定義異常處理
    :param exc: 異常類
    :param context: 拋出異常的上下文
    :return: Response響應對象
    """
    # 調用drf框架原生的異常處理方法
    response = exception_handler(exc, context)

    if response is None:
        view = context['view']
        if isinstance(exc, DatabaseError):
            # 數據庫異常
            logger.error('[%s] %s' % (view, exc))
            response = Response({'message': '服務器內部錯誤'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)

    return response

settings/dev.py配置文件中添加

REST_FRAMEWORK = {
    # 異常處理
    'EXCEPTION_HANDLER': 'luffy.utils.exceptions.custom_exception_handler',
}

4.7 創建數據庫

create database luffycity default charset=utf8;

1557450273503

為當前項目創建數據庫用戶[這個用戶只能看到這個數據庫]

create user luffy_user identified by 'luffy';
grant all privileges on luffycity.* to 'luffy_user'@'%';
flush privileges;

1557450379001

4.8 配置數據庫連接

打開settings/dev.py文件,並配置

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "HOST": "127.0.0.1",
        "PORT": 3306,
        "USER": "luffy_user",
        "PASSWORD": "luffy",
        "NAME": "luffycity",
    }
}

在項目主模塊的 __init__.py中導入pymysql

import pymysql

pymysql.install_as_MySQLdb()

調整錯誤

數據庫版本檢測導致的錯誤

1557453985484

數據庫的版本檢測代碼注釋掉。、

1557454099123

第二個錯誤也是因為數據庫版本的默認編碼導致,query返回的內容格式使用有誤。

新增一行代碼,把query查詢結果轉換格式為 bytes類型

1557454044879

5. 搭建前端項目

5.1 創建項目目錄

cd 項目目錄
vue init webpack lufei_pc

例如,我要把項目保存在~/Desktop桌面目錄下,可以如下操作:

cd ~/Desktop
vue init webpack lufei_pc

根據需要在生成項目時,我們選擇對應的選項, 效果:

1557451009689

根據上面的提示,我們已經把vue項目構建好了,運行測試服務器。

1557451125218

打開項目已經,在pycharm的終端下運行vue項目,查看效果。

npm run dev

接下來,我們根據終端上效果顯示的對應地址來訪問項目(如果有多個vue項目在運行,8080端口被占據了,服務器會自動改端口,所以根據自己實際在操作中看到的地址來訪問。)

訪問:http://localost:8080。效果:

1557451188340

我們也可以把我們的前端項目進行git源代碼管理

5.2 初始化前端項目

清除默認的HelloWorld組件和APP.vue中的默認樣式

1557451289161

接下來,我們可以查看效果了,一張白紙~

1557451300406

5.3 安裝路由vue-router

5.3.1 下載路由組件

npm i vue-router -S

執行效果:

1557451350882

5.3.2 配置路由

5.3.2.1 初始化路由對象

在src目錄下創建routers路由目錄,在routers目錄下創建index.js路由文件

index.js路由文件中,編寫初始化路由對象的代碼 .

import Vue from "vue"
import Router from "vue-router"

// 這里導入可以讓讓用戶訪問的組件

Vue.use(Router);

export default new Router({
  // 設置路由模式為‘history’,去掉默認的#
  mode: "history",
  routes:[
    // 路由列表

  ]
})

1557451480681

5.3.2.2 注冊路由信息

打開main.js文件,把router對象注冊到vue中.代碼:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './routers/index';

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
});

1557451533378

5.3.2.3 在視圖中顯示路由對應的內容

在App.vue組件中,添加顯示路由對應的內容。

1557451572377

代碼:

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App',
  components: {

  }
}
</script>

<style>

</style>

5.3.2.4 創建並提供前端首頁的組件

routers/index.js

// import Vue from "vue"
// import Router from "vue-router"
//
//
// // 這里導入可以讓讓用戶訪問的組件
import Home from "../components/Home"
// Vue.use(Router);
//
// export default new Router({
//   // 設置路由模式為‘history’,去掉默認的#
//   mode: "history",
//   routes:[
//     // 路由列表
     {
       name:"Home",
       path:"/",
       component:Home,
     },
      {
       name:"Home",
       path:"/home",
       component:Home,
     },
   ]
// })

創建Home組件

components/Home.vue

<template>
  <div id="home">
    前端首頁
  </div>
</template>
<script>
  export default {
      name:"Home",
      data(){
          return {
              
          }
      }
  }
</script>

<style scoped>

</style>

1557451775965

5.4 前端初始化全局變量和全局方法

在src目錄下創建settings.js站點開發配置文件:

export default {
  Host:"http://127.0.0.1",
}

在main.js中引入

// // The Vue build version to load with the `import` command
// // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
// import Vue from 'vue'
// import App from './App'
// import router from './routers/index';
import settings from "./settings"
// Vue.config.productionTip = false;
Vue.prototype.$settings = settings;
//
// /* eslint-disable no-new */
// new Vue({
//   el: '#app',
//   router,
//   components: { App },
//   template: '<App/>'
// });

5.5 引入ElementUI

npm i element-ui -S

上面的命令等同於

npm install element-ui --save

執行命令效果:

1557452146253

5.5.1 配置ElementUI到項目中

在main.js中導入ElementUI,並調用。

代碼:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
// import Vue from 'vue'
// import App from './App'
// import router from './routers/index';

// 開發配置文件
// import settings from "./settings"
// Vue.prototype.$settings = settings;

// elementUI 導入
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
// 調用插件
Vue.use(ElementUI);


// Vue.config.productionTip = false;

/* eslint-disable no-new */
// new Vue({
//   el: '#app',
//   router,
//   components: { App },
//   template: '<App/>'
// });

效果:

1557452192638

成功引入了ElementUI以后,接下來我們就可以開始進入前端頁面開發,首先是首頁。

接下來我們把之前完成的首頁,直接拿過來使用[注意除了組件以外,還有靜態文件也需要拿過來,包括App.vue里面的公共樣式],並運行項目。

App.vue,全局css初始化代碼

<style>
  body,h1,h2,h3,h4,h5,ul,p{
    padding: 0;
    margin:0;
    font-weight: normal;
  }
  body{
    margin-top: 80px;
  }
  a{
    text-decoration: none;
    color: #4a4a4a;
  }
  a:hover{
    color: #000;
  }

  ul{
    list-style: none;
  }

  img{
    width: 100%;
  }

  .header .el-menu li .el-submenu__title{
    height: 26px!important;
    line-height: 26px!important;
  }
  .el-menu--popup{
    min-width: 140px;
  }
  .el-checkbox__inner{
    width:16px;
    height: 16px;
    border: 1px solid #999;
  }
  .el-checkbox__inner:after{
    width: 6px;
    height: 8px;
  }
  .el-form-item__content{
    margin-left:0px!important;
    width: 120px;
  }
</style>

Home.vue中添加代碼:

<template>
  <div id="home">
    <Header/>
    <Banner/>
    <Footer/>
  </div>
</template>

<script>
import Header from "./common/Header"
import Banner from "./common/Banner"
import Footer from "./common/Footer"

export default {
  name:"Home",
  data(){
    return {

    }
  },
  components:{
    Header,
    Banner,
    Footer,
  }
}
</script>

<style scoped>

</style>

components/common/Header.vue

<template>
  <div class="header">
    <el-container>
      <el-header>
        <el-row>
          <el-col class="logo" :span="3">
            <a href="/">
              <img src="@/assets/head-logo.svg" alt="">
            </a>
          </el-col>
          <el-col class="nav" :span="16">
              <el-row>
                <el-col :span="3"><router-link class="current" to="/course">免費課</router-link></el-col>
                <el-col :span="3"><router-link to="/">輕課</router-link></el-col>
                <el-col :span="3"><router-link to="/">學位課</router-link></el-col>
                <el-col :span="3"><router-link to="/">題庫</router-link></el-col>
                <el-col :span="3"><router-link to="/">教育</router-link></el-col>
              </el-row>
          </el-col>
          <el-col class="login-bar" :span="5">
            <el-row v-if="token">
              <el-col class="cart-ico" :span="9">
                <router-link to="">
                  <b class="goods-number">0</b>
                  <img class="cart-icon" src="@/assets/cart.svg" alt="">
                  <span><router-link to="/cart">購物車</router-link></span>
                </router-link>
              </el-col>
              <el-col class="study" :span="8" :offset="2"><router-link to="">學習中心</router-link></el-col>
              <el-col class="member" :span="5">
                <el-menu class="el-menu-demo" mode="horizontal">
                  <el-submenu index="2">
                    <template slot="title"><router-link to=""><img src="@/assets/logo@2x.png" alt=""></router-link></template>
                    <el-menu-item index="2-1">我的賬戶</el-menu-item>
                    <el-menu-item index="2-2">我的訂單</el-menu-item>
                    <el-menu-item index="2-3">我的優惠卷</el-menu-item>
                    <el-menu-item index="2-3">退出登錄</el-menu-item>
                  </el-submenu>
                </el-menu>
              </el-col>
            </el-row>
            <el-row v-else>
              <el-col class="cart-ico" :span="9">
                <router-link to="">
                  <img class="cart-icon" src="@/assets/cart.svg" alt="">
                  <span><router-link to="/cart">購物車</router-link></span>
                </router-link>
              </el-col>
              <el-col :span="10" :offset="5">
                <span class="register">
                  <router-link to="/login">登錄</router-link>
                  &nbsp;&nbsp;|&nbsp;&nbsp;
                  <router-link to="/register">注冊</router-link>
                </span>
              </el-col>
            </el-row>
          </el-col>
        </el-row>
      </el-header>
    </el-container>
  </div>
</template>

<script>
  export default {
    name: "Header",
    data(){
      return {
        // 設置一個登錄標識,表示是否登錄
        token: false,
      };
    }
  }
</script>

<style scoped>
  .header{
    top:0;
    left:0;
    right:0;
    margin: auto;
    background-color: #fff;
    height: 80px;
    z-index: 1000;
    position: fixed;
    box-shadow: 0 0.5px 0.5px 0 #c9c9c9;
  }
  .header .el-container{
    width: 1200px;
    margin: 0 auto;
  }
  .el-header{
    height: 80px!important;
    padding:0;
  }
  .logo{

  }
  .logo img{
    padding-top: 22px;
  }

  .nav{
    margin-top: 22px;
  }

  .nav .el-col a{
    display: inline-block;
    text-align: center;
    padding-bottom: 16px;
    padding-left: 5px;
    padding-right: 5px;
    position: relative;
    font-size: 16px;
    margin-left: 20px;
  }

  .nav .el-col .current{
    color: #4a4a4a;
    border-bottom: 4px solid #ffc210;
  }

  .login-bar{
    margin-top: 22px;
  }
  .cart-ico{
    position: relative;
    border-radius: 17px;
  }
  .cart-ico:hover{
    background: #f0f0f0;
  }
  .goods-number{
    width: 16px;
    height: 16px;
    line-height: 17px;
    font-size: 12px;
    color: #fff;
    text-align: center;
    background: #fa6240;
    border-radius: 50%;
    transform: scale(.8);
    position: absolute;
    left: 16px;
    top: -1px;
  }
  .cart-icon{
    width: 15px;
    height: auto;
    margin-left: 6px;
  }
  .cart-ico span{
    margin-left: 12px;
  }
  .member img{
    width: 26px;
    height: 26px;
    border-radius: 50%;
    display: inline-block;
  }
  .member img:hover{
    border: 1px solid yellow;
  }

</style>

components/common/Bannner.vue

<template>
  <div class="banner">
      <el-carousel trigger="click" height="473px">
        <el-carousel-item v-for="banner in banner_list">
          <a :href="banner.link"><img width="100%" :src="banner.img" alt=""></a>
        </el-carousel-item>
      </el-carousel>
  </div>
</template>

<script>
  export default {
    name:"Banner",
    data(){
      return {
        banner_list:[
          {link:"http://www.baidu.com",img:"/static/banner/1.png"},
          {link:"http://www.baidu.com",img:"/static/banner/2.png"},
          {link:"http://www.baidu.com",img:"/static/banner/3.png"},
        ]
      };
    }
  }
</script>

<style>
.el-carousel__arrow{
  width: 100px!important;
  height: 100px!important;
}
.el-icon-arrow-left{
  font-size: 35px;
  margin-left: 50px;
}
.el-carousel__arrow--left{
  left: -50px;
}
</style>

components/common/Footer.vue

<template>
  <div class="footer">
    <el-container>
      <el-row>
        <el-col :span="4"><router-link to="">關於我們</router-link></el-col>
        <el-col :span="4"><router-link to="">聯系我們</router-link></el-col>
        <el-col :span="4"><router-link to="">商務合作</router-link></el-col>
        <el-col :span="4"><router-link to="">幫助中心</router-link></el-col>
        <el-col :span="4"><router-link to="">意見反饋</router-link></el-col>
        <el-col :span="4"><router-link to="">新手指南</router-link></el-col>
        <el-col :span="24"><p class="copyright">Copyright © luffycity.com版權所有 | 京ICP備17072161號-1</p></el-col>
      </el-row>
    </el-container>
  </div>
</template>

<script>
  export default {
    name:"Footer",
    data(){
      return {}
    }
  }
</script>


<style scoped>
.footer{
  width: 100%;
  height: 128px;
  background: #25292e;
}
.footer .el-container{
  width: 1200px;
  margin: auto;
}
.footer .el-row {
  align-items: center;
  padding: 0 200px;
  padding-bottom: 15px;
  width: 100%;
  margin-top: 38px;
}
.footer .el-row a{
  color: #fff;
  font-size: 14px;
}
.footer .el-row .copyright{
  text-align: center;
  color: #fff;
  font-size: 14px;
}
</style>

也可以把App.vue的style標簽的css代碼放到static外部目錄下引用過來

main.js

import "../static/css/reset.css";

reset.css

body,h1,h2,h3,h4,h5,ul,p{
    padding: 0;
    margin:0;
    font-weight: normal;
  }
  body{
    margin-top: 80px;
  }
  a{
    text-decoration: none;
    color: #4a4a4a;
  }
  a:hover{
    color: #000;
  }

  ul{
    list-style: none;
  }

  img{
    width: 100%;
  }

  .header .el-menu li .el-submenu__title{
    height: 26px!important;
    line-height: 26px!important;
  }
  .el-menu--popup{
    min-width: 140px;
  }
  .el-checkbox__inner{
    width:16px;
    height: 16px;
    border: 1px solid #999;
  }
  .el-checkbox__inner:after{
    width: 6px;
    height: 8px;
  }
  .el-form-item__content{
    margin-left:0px!important;
    width: 120px;
  }

6. 跨域CORS

我們現在為前端和后端分別設置兩個不同的域名:

位置 域名
前端 www.luffycity.cn
后端 api.luffycity.cn

編輯/etc/hosts文件,可以設置本地域名

sudo vim /etc/hosts

在文件中增加兩條信息

127.0.0.1   localhost
127.0.0.1   api.luffycity.cn
127.0.0.1   www.luffycity.cn

1557454299594

通過瀏覽器訪問前端vue項目,會出現nginx的歡迎頁面,主要因為我們當前項目已經有一個nginx監聽了80端口,所以訪問www.luffycity.cn網址時,會自動被轉發到127.0.0.1本機,因為沒有網址默認端口是80端口,所以被nginx進行處理了當前請求,因此我們暫時先把nginx關閉先。

# 查找nginx的進程
ps -ef|grep nginx
# 關閉進程
sudo kill -9 nginx進程號

1557454528245

關閉了nginx以后,訪問www.luffy.cirty.cn網址,效果:

1557454604654

上面並不是錯誤,而是沒人監聽了這個地址和端口了,解決方法:

暫停運行前端項目,並修改配置文件config/index.js

    host: 'www.luffycity.cn', // can be overwritten by process.env.HOST
    port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
    autoOpenBrowser: true,

保存修改信息,並重啟項目

1557454684623

通過瀏覽器訪問drf項目,會出現以下錯誤信息

1557454965635

可以通過settings/dev.py的ALLOWED_HOSTS,設置允許訪問

# 設置哪些客戶端可以通過地址訪問到后端
ALLOWED_HOSTS = [
    'api.luffycity.cn',
]

1557455086164

讓用戶訪問的時候,使用api.luffycity.cn:8000

1. 修改pycharm的manage.py的配置參數

1557455152863

現在,前端與后端分處不同的域名,我們需要為后端添加跨域訪問的支持

否則前端無法使用axios無法請求后端提供的api數據,我們使用CORS來解決后端對跨域訪問的支持。

使用django-cors-headers擴展

在 Response(headers={"Access-Control-Allow-Origin":'客戶端地址/*'})

文檔:https://github.com/ottoyiu/django-cors-headers/

安裝

pip install django-cors-headers

添加應用

INSTALLED_APPS = (
    ...
    'corsheaders',
    ...
)

中間層設置【必須寫在第一個位置】

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    ...
]

添加白名單

# CORS組的配置信息
CORS_ORIGIN_WHITELIST = (
    'www.luffycity.cn:8080'
)
CORS_ALLOW_CREDENTIALS = True  # 允許ajax跨域請求時攜帶cookie

1557455675163

完成了上面的步驟,我們就可以通過后端提供數據給前端使用ajax訪問了。

前端使用 axios就可以訪問到后端提供給的數據接口,但是如果要附帶cookie信息,前端還要設置一下。

前端引入axios插件並配置允許axios發送cookie信息[axios本身也不允許ajax發送cookie到后端]

npm i axios -S

1557455747921

在main.js中引用 axios插件

import axios from 'axios'; // 從node_modules目錄中導入包
// 允許ajax發送請求時附帶cookie
axios.defaults.withCredentials = true;

Vue.prototype.$axios = axios; // 把對象掛載vue中


免責聲明!

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



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