1. Vue+Django+DRF项目搭建案例
1.1 企业的web项目类型
1.2 企业项目开发流程
1.3 立项申请阶段
2. 需求分析
2.1 首页
2.2 登录注册
2.3 课程列表
2.4 课程详情
2.5 购物车
2.6 商品结算
2.7 购买成功
2.8 个人中心
2.9 视频播放
3. 环境搭建
3.1 创建虚拟环境
3.2 相关命令复习
3.3 依赖包安装
4. 搭建项目
4.1 创建项目
4.3 打开项目
4.2 调整目录
4.2.1 分不同环境进行项目配置
4.3 创建代码版本
4.3.1 配置用户名和邮箱
4.4 在git平台创建工程
4.5 日志配置
4.6 异常处理
4.7 创建数据库
4.8 配置数据库连接
5. 搭建前端项目
5.1 创建项目目录
5.2 初始化前端项目
5.3 安装路由vue-router
5.3.1 下载路由组件
5.3.2 配置路由
5.4 前端初始化全局变量和全局方法
5.5 引入ElementUI
5.5.1 配置ElementUI到项目中
6. 跨域CORS
商城
1.1 B2C 直销商城 商家与会员直接交易 ( Business To Customer )
1.2 B2B 批发商城 商家与商家直接交易
1.3 B2B2C 购物平台 商家和会员在另一个商家提供的平台上面进行交易
1.4 C2B 定制商城 会员向商家发起定制商品的需求,商家去完成。
1.5 O2O 线上线下交易平台
1.6 C2C 二手交易平台
门户网站[企业站和门户站]
社交网络
资讯论坛
内部系统
个人博客
内容收费站
立项其实就是对产品项目能不能做和怎么做,提出理论基础。大的互联网公司都有比较正规的立项流程。
通常公司内部要研发一款软硬件的产品之前,都要经过市场评估和调研分析,产生一份产品项目立项报告
给公司。
产品项目立项报告一般包含以下内容:
项目概述
需求市场
需求分析和项目建设的必要性
业务分析
总体建设方案
项目风险和风险管理
可行性分析阶段
参考资料:https://blog.csdn.net/m0_37370820/article/details/81077886
功能:导航菜单、轮播图、退出登录
功能:用户登录、极验验证码、多条件登录、记住密码、短信发送、短信冷却倒计时、jwt认证
功能:课程分类、课程列表、课程多条件筛选展示、课程分类展示、课程分页展示、课程章节课时展示、课程优惠策略
功能:课程信息展示、视频播放、富文本编辑器
功能:购物车商品列表、添加商品、删除商品、勾选商品状态、商品结算、订单生成、唯一订单号生成
功能:订单商品信息列表、订单信息展示、积分计算功能、优惠券策略、课程有效期计算、第三方支付平台接口
功能列表:我的订单、订单状态改变
功能:视频加密播放
mkvirtualenv luffy
如果自己的开发机子中存在多个版本的python,则可以指定解析器的版本
mkvirtualenv luffy -p python3
创建虚拟环境: 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解析器,对于源代码是毫无关系
创建虚拟环境需要联网
创建成功后, 会自动工作在这个虚拟环境上
工作在虚拟环境上, 提示符最前面会出现 “(虚拟环境名称)”
pip install djangopip install djangorestframework
pip install PymySQL
pip install Pillow
pip install django-redis
django-admin startproject luffy
效果:
在pycharm中打开项目
设置虚拟环境
启动django项目
use the manage.py
not pycharm default start button
效果:
提示:
在pycharm中如果要使用已经创建好的虚拟环境,则必须设置pycharm中的python解释器,设置为虚拟环境中的python。
├── docs/ # 项目相关资料保存目录├── logs/ # 项目运行时/开发时日志目录├── manage.py ├── luffy/ # 项目主应用,开发时的代码保存│ ├── apps/ # 开发者的代码保存目录,以模块[子应用]为目录保存│ ├── libs/ # 第三方类库的保存目录[第三方组件、模块]│ ├── settings/ │ ├── dev.py # 项目开发时的本地配置│ ├── prop.py # 项目上线时的运行配置│ ├── urls.py # 总路由│ ├── utils/ # 多个模块[子应用]的公共函数类库[自己开发的组件]└── scripts/ # 保存项目运营时的脚本文件
开发者本地的环境、目录、数据库密码和线上的服务器都会不一样,所以我们的配置文件可以针对不同的系统分成多分.
在项目主应用下,创建一个settings的配置文件存储目录
根据线上线下两种情况分别创建2个配置文件 dev.py和prod.py
把原来项目主应用的 settings.py配置内容复制2份到dev.py和prod.py里面
把原来的settings.py配置文件修改文件名或者删除
新的目录settings:
接下来,就可以根据在manage.py中根据不同的情况导入对应的配置文件了.
cd进入到自己希望存储代码的目录路径,并创建本地仓库.git【pycharm直接打开终端就是项目根目录了。无须cd了】
新创建的本地仓库.git是个空仓库
cd 目录路径
git init
git config --global user.name 'lisi'git config --global user.email 'lisi@163.com'
公司一般都会有自己的代码仓库,一般都是自己搭建,也有使用第三方提供代码管理平台。
常用的代码管理平台: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管理工具来完成代码的拉取和推送。
在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, # 是否让日志信息继续冒泡给其他的日志处理系统
},
}
}
新建utils/exceptions.py
from rest_framework.views import exception_handlerfrom 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)
<span class='hljs-keyword'>if</span> response <span class='hljs-keyword'>is</span> <span class='hljs-keyword'>None</span>:
view = context[<span class='hljs-string'>'view'</span>]
<span class='hljs-keyword'>if</span> isinstance(exc, DatabaseError):
<span class='hljs-comment'># 数据库异常</span> logger.error(<span class='hljs-string'>'[%s] %s'</span> % (view, exc)) response = Response({<span class='hljs-string'>'message'</span>: <span class='hljs-string'>'服务器内部错误'</span>}, status=status.HTTP_507_INSUFFICIENT_STORAGE)
<span class='hljs-keyword'>return</span> response</code></pre>
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 pymysqlpymysql.install_as_MySQLdb()
调整错误
数据库版本检测导致的错误
数据库的版本检测代码注释掉。、
第二个错误也是因为数据库版本的默认编码导致,query返回的内容格式使用有误。
新增一行代码,把query查询结果转换格式为 bytes类型
回到顶部(go to top)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;
}
回到顶部(go to top)6. 跨域CORS
我们现在为前端和后端分别设置两个不同的域名:
位置 域名 前端 www.luffycity.cn
后端 api.luffycity.cn
编辑/etc/hosts
文件,可以设置本地域名
sudo vim /etc/hosts
在文件中增加两条信息
127.0.0.1 localhost127.0.0.1 api.luffycity.cn127.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发送请求时附带cookieaxios.defaults.withCredentials = true;Vue.prototype.$axios = axios; // 把对象挂载vue中
联系客服