1. Vue+Django+DRF項目搭建案例
1.1 企業的web項目類型
-
商城
1.1 B2C 直銷商城 商家與會員直接交易 ( Business To Customer )
1.2 B2B 批發商城 商家與商家直接交易
1.3 B2B2C 購物平台 商家和會員在另一個商家提供的平台上面進行交易
1.4 C2B 定制商城 會員向商家發起定制商品的需求,商家去完成。
1.5 O2O 線上線下交易平台
1.6 C2C 二手交易平台
-
門戶網站[企業站和門戶站]
-
社交網絡
-
資訊論壇
-
內部系統
-
個人博客
-
內容收費站
1.2 企業項目開發流程
1.3 立項申請階段
立項其實就是對產品項目能不能做和怎么做,提出理論基礎。大的互聯網公司都有比較正規的立項流程。
通常公司內部要研發一款軟硬件的產品之前,都要經過市場評估和調研分析,產生一份產品項目立項報告
給公司。
產品項目立項報告一般包含以下內容:
項目概述
需求市場
需求分析和項目建設的必要性
業務分析
總體建設方案
項目風險和風險管理
可行性分析階段
參考資料:https://blog.csdn.net/m0_37370820/article/details/81077886
2. 需求分析
2.1 首頁
功能:導航菜單、輪播圖、退出登錄
2.2 登錄注冊
功能:用戶登錄、極驗驗證碼、多條件登錄、記住密碼、短信發送、短信冷卻倒計時、jwt認證
2.3 課程列表
功能:課程分類、課程列表、課程多條件篩選展示、課程分類展示、課程分頁展示、課程章節課時展示、課程優惠策略
2.4 課程詳情
功能:課程信息展示、視頻播放、富文本編輯器
2.5 購物車
功能:購物車商品列表、添加商品、刪除商品、勾選商品狀態、商品結算、訂單生成、唯一訂單號生成
2.6 商品結算
功能:訂單商品信息列表、訂單信息展示、積分計算功能、優惠券策略、課程有效期計算、第三方支付平台接口
2.7 購買成功
2.8 個人中心
功能列表:我的訂單、訂單狀態改變
2.9 視頻播放
功能:視頻加密播放
3. 環境搭建
3.1 創建虛擬環境
mkvirtualenv luffy
如果自己的開發機子中存在多個版本的python,則可以指定解析器的版本
mkvirtualenv luffy -p python3
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
效果:
4.3 打開項目
在pycharm中打開項目
設置虛擬環境
啟動django項目
use the manage.py
not pycharm default start button
效果:
提示:
在pycharm中如果要使用已經創建好的虛擬環境,則必須設置pycharm中的python解釋器,設置為虛擬環境中的python。
4.2 調整目錄
├── docs/ # 項目相關資料保存目錄
├── logs/ # 項目運行時/開發時日志目錄
├── manage.py
├── luffy/ # 項目主應用,開發時的代碼保存
│ ├── apps/ # 開發者的代碼保存目錄,以模塊[子應用]為目錄保存
│ ├── libs/ # 第三方類庫的保存目錄[第三方組件、模塊]
│ ├── settings/
│ ├── dev.py # 項目開發時的本地配置
│ ├── prop.py # 項目上線時的運行配置
│ ├── urls.py # 總路由
│ ├── utils/ # 多個模塊[子應用]的公共函數類庫[自己開發的組件]
└── scripts/ # 保存項目運營時的腳本文件
4.2.1 分不同環境進行項目配置
開發者本地的環境、目錄、數據庫密碼和線上的服務器都會不一樣,所以我們的配置文件可以針對不同的系統分成多分.
- 在項目主應用下,創建一個settings的配置文件存儲目錄
- 根據線上線下兩種情況分別創建2個配置文件 dev.py和prod.py
- 把原來項目主應用的 settings.py配置內容復制2份到dev.py和prod.py里面
- 把原來的settings.py配置文件修改文件名或者刪除
新的目錄settings:
接下來,就可以根據在manage.py中根據不同的情況導入對應的配置文件了.
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) 創建私有項目庫
創建私有空倉庫以后的界面:
2)克隆項目到本地
注意:
我們當前項目不需要這個步驟
這個步驟是 當以后我們進入公司里面,參與人家已經在做的項目時,別人已經有倉庫了,但是我們是新人加入項目中的,那么我們不需要在自己本地進行git init,直接git clone 復制別人的倉庫代碼
git clone 倉庫地址
注意,如果當前目錄下出現git倉庫同名目錄時,會克隆失敗。
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平台。效果:
上面雖然成功移交了代碼版本,但是一些不需要的文件也被提交上去了。
所以,我們針對一些不需要的文件,可以選擇從代碼版本中刪除,並且使用.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管理工具來完成代碼的拉取和推送。
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;
為當前項目創建數據庫用戶[這個用戶只能看到這個數據庫]
create user luffy_user identified by 'luffy';
grant all privileges on luffycity.* to 'luffy_user'@'%';
flush privileges;
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()
調整錯誤
數據庫版本檢測導致的錯誤
數據庫的版本檢測代碼注釋掉。、
第二個錯誤也是因為數據庫版本的默認編碼導致,query返回的內容格式使用有誤。
新增一行代碼,把query查詢結果轉換格式為 bytes類型
5. 搭建前端項目
5.1 創建項目目錄
cd 項目目錄
vue init webpack lufei_pc
例如,我要把項目保存在~/Desktop桌面目錄下,可以如下操作:
cd ~/Desktop
vue init webpack lufei_pc
根據需要在生成項目時,我們選擇對應的選項, 效果:
根據上面的提示,我們已經把vue項目構建好了,運行測試服務器。
打開項目已經,在pycharm的終端下運行vue項目,查看效果。
npm run dev
接下來,我們根據終端上效果顯示的對應地址來訪問項目(如果有多個vue項目在運行,8080端口被占據了,服務器會自動改端口,所以根據自己實際在操作中看到的地址來訪問。)
訪問:http://localost:8080。效果:
我們也可以把我們的前端項目進行git源代碼管理
5.2 初始化前端項目
清除默認的HelloWorld組件和APP.vue中的默認樣式
接下來,我們可以查看效果了,一張白紙~
5.3 安裝路由vue-router
5.3.1 下載路由組件
npm i vue-router -S
執行效果:
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:[
// 路由列表
]
})
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/>'
});
5.3.2.3 在視圖中顯示路由對應的內容
在App.vue組件中,添加顯示路由對應的內容。
代碼:
<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>
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
執行命令效果:
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/>'
// });
效果:
成功引入了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>
|
<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
通過瀏覽器訪問前端vue項目,會出現nginx的歡迎頁面,主要因為我們當前項目已經有一個nginx監聽了80端口,所以訪問www.luffycity.cn網址時,會自動被轉發到127.0.0.1本機,因為沒有網址默認端口是80端口,所以被nginx進行處理了當前請求,因此我們暫時先把nginx關閉先。
# 查找nginx的進程
ps -ef|grep nginx
# 關閉進程
sudo kill -9 nginx進程號
關閉了nginx以后,訪問www.luffy.cirty.cn網址,效果:
上面並不是錯誤,而是沒人監聽了這個地址和端口了,解決方法:
暫停運行前端項目,並修改配置文件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,
保存修改信息,並重啟項目
通過瀏覽器訪問drf項目,會出現以下錯誤信息
可以通過settings/dev.py的ALLOWED_HOSTS,設置允許訪問
# 設置哪些客戶端可以通過地址訪問到后端
ALLOWED_HOSTS = [
'api.luffycity.cn',
]
讓用戶訪問的時候,使用api.luffycity.cn:8000
1. 修改pycharm的manage.py的配置參數
現在,前端與后端分處不同的域名,我們需要為后端添加跨域訪問的支持
否則前端無法使用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
完成了上面的步驟,我們就可以通過后端提供數據給前端使用ajax訪問了。
前端使用 axios就可以訪問到后端提供給的數據接口,但是如果要附帶cookie信息,前端還要設置一下。
前端引入axios插件並配置允許axios發送cookie信息[axios本身也不允許ajax發送cookie到后端]
npm i axios -S
在main.js中引用 axios插件
import axios from 'axios'; // 從node_modules目錄中導入包
// 允許ajax發送請求時附帶cookie
axios.defaults.withCredentials = true;
Vue.prototype.$axios = axios; // 把對象掛載vue中