今日内容概要
-
下单接口前端
-
前端get回调和支付宝post回调
-
扫码登陆功能
-
上线前准备
-
阿里云购买
-
安装git
-
安装mysql
-
安装redis
-
安装python
-
安装虚拟环境
-
安装uwsgi
-
安装nginx
-
部署前端项目
-
部署后台项目
-
安全组
-
127.0.0.1与0.0.0.0区别
今日内容详细
补充
设置jwt过期时间
import datetime
JWT_AUTH = {
# 过期时间7天
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
}
支付宝支付流程
在咱们前端,点击购买(下单)---->咱们后端发送请求----->到咱们后端,把携带的商品信息,入库(订单库)--->生成的支付链接,返回给前端---->前端拿到支付链接--->打开支付链接--->看到支付宝付款页面--->手机扫描付款,直接输入用户名密码付款---->付款成功,支付宝收到了----->让前端回调回咱们的前端(配置)(get回调)---->等待支付宝post回调(回调后端,配置)--->这个回调中验签--->修改订单状态--->过程结束
location.search
在JavaScript中,location.search 是一个包含当前页面 URL 查询参数的字符串。当浏览器加载一个 URL 时,查询参数是 URL 中问号(?)后面的部分,包含一个或多个键值对。location.search 返回的字符串包括问号(?)以及后面的所有查询参数。
//假设当前页面 URL 是 https://www.example.com/?name=John&age=25
// 创建 URLSearchParams 对象
var params = new URLSearchParams(location.search);
// 获取特定查询参数的值
var name = params.get('name');
console.log(name); // 输出: John
var age = params.get('age');
console.log(age); // 输出: 25
substring()
location.search.substring(1) 是将 location.search 字符串的第一个字符(问号?)去除后的子字符串。
在 JavaScript 中,substring() 方法用于提取字符串中指定范围的子字符串。该方法接受两个参数:起始索引和结束索引(可选)。如果省略结束索引,则提取从起始索引到字符串末尾的所有字符。
在这种情况下,location.search 是一个包含查询参数的字符串,例如 ?name=John&age=25。通过调用 substring(1),我们从第一个字符开始提取子字符串,也就是去除了第一个字符的 name=John&age=25
下单接口前端
CourseDetail.vue
<button class="buy-now" @click="HandelGoPay">立即购买</button>
HandelGoPay() {
//1.判断登陆没有
let token = this.$cookies.get('token')
if (!token){
this.$message('请登录再购买哦')
return
}
//2.发送请求
const config={
headers:{
Authorization:'jwt '+token
}
}
this.$axios.post(`${this.$settings.BASE_URL}order/pay/`, {
"subject": this.course_info.name,
"total_amount": this.course_info.price,
"pay_type": 1,
"courses": [this.course_info.id]
},config).then(res=>{
if (res.data.code==100){
//获取pay_url
const pay_url=res.data.pay_url
open(pay_url,'_self')
}else {
//获取失败
this.$message('下单失败')
}
})
},
前端get回调和支付宝post回调
前端get回调
前端回调页面
<template>
<div class="pay-success">
<!--如果是单独的页面,就没必要展示导航栏(带有登录的用户)-->
<Header/>
<div class="main">
<div class="title">
<div class="success-tips">
<p class="tips">您已成功购买 1 门课程!</p>
</div>
</div>
<div class="order-info">
<p class="info"><b>订单号:</b><span>{{ result.out_trade_no }}</span></p>
<p class="info"><b>交易号:</b><span>{{ result.trade_no }}</span></p>
<p class="info"><b>付款时间:</b><span><span>{{ result.timestamp }}</span></span></p>
</div>
<div class="study">
<span>立即学习</span>
</div>
</div>
</div>
</template>
<script>
import Header from "@/components/Header"
export default {
name: "Success",
data() {
return {
result: {},
};
},
created() {
// url后拼接的参数:?及后面的所有参数 => ?a=1&b=2
// console.log(location.search);
//http://127.0.0.1:8080/pay/success?charset=utf-8&out_trade_no=f1692dff-26ed-431b-be92-b76b76fa52c0&method=alipay.trade.page.pay.return&total_amount=199.00&...
// 解析支付宝回调的url参数
let params = location.search.substring(1); // 去除? => a=1&b=2
let items = params.length ? params.split('&') : []; // ['a=1', 'b=2']
//逐个将每一项添加到args对象中
for (let i = 0; i < items.length; i++) { // 第一次循环a=1,第二次b=2
let k_v = items[i].split('='); // ['a', '1']
//解码操作,因为查询字符串经过编码的
if (k_v.length >= 2) {
// url编码反解
let k = decodeURIComponent(k_v[0]);
this.result[k] = decodeURIComponent(k_v[1]);
// 没有url编码反解
// this.result[k_v[0]] = k_v[1];
}
}
// 解析后的结果
console.log(this.result);
// 把地址栏上面的支付结果,再get请求转发给后端
this.$axios({
url: this.$settings.BASE_URL + '/order/success/' + location.search,
method: 'get',
}).then(response => {
console.log(response.data);
}).catch(() => {
console.log('支付结果同步失败');
})
},
components: {
Header,
}
}
</script>
<style scoped>
.main {
padding: 60px 0;
margin: 0 auto;
width: 1200px;
background: #fff;
}
.main .title {
display: flex;
-ms-flex-align: center;
align-items: center;
padding: 25px 40px;
border-bottom: 1px solid #f2f2f2;
}
.main .title .success-tips {
box-sizing: border-box;
}
.title img {
vertical-align: middle;
width: 60px;
height: 60px;
margin-right: 40px;
}
.title .success-tips {
box-sizing: border-box;
}
.title .tips {
font-size: 26px;
color: #000;
}
.info span {
color: #ec6730;
}
.order-info {
padding: 25px 48px;
padding-bottom: 15px;
border-bottom: 1px solid #f2f2f2;
}
.order-info p {
display: -ms-flexbox;
display: flex;
margin-bottom: 10px;
font-size: 16px;
}
.order-info p b {
font-weight: 400;
color: #9d9d9d;
white-space: nowrap;
}
.study {
padding: 25px 40px;
}
.study span {
display: block;
width: 140px;
height: 42px;
text-align: center;
line-height: 42px;
cursor: pointer;
background: #ffc210;
border-radius: 6px;
font-size: 16px;
color: #fff;
}
</style>
后端:前端回调get请求
from rest_framework.viewsets import GenericViewSet
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated
class PayOrderView(GenericViewSet):
serializer_class = OlderSerializer
authentication_classes = [JSONWebTokenAuthentication]
permission_classes = [IsAuthenticated]
def create(self,request,*args,**kwargs):
ser = self.get_serializer(data = request.data,context={"request":request})
ser.is_valid(raise_exception=True)
ser.save()
pay_url = ser.context.get('pay_url')
return APIResponse(pay_url=pay_url)
from rest_framework.viewsets import ViewSet
from .models import Order
class SuccessView(ViewSet):
def get(self,request,*args,**kwargs):
# 根据订单号,查看是否是是一直已经支付的状态
try:
out_trade_no= request.query_params.get('out_trade_no')
Order.objects.get(order_status=1,out_trade_no=out_trade_no)
return APIResponse()
except Exception as e:
return APIResponse(code=101,msg='订单没有支付')
路由
from .views import SuccessView
urlpatterns = [
path('success/', SuccessView.as_view({'get':'get','post':'post'})),
]
支付宝post回调
1.因为我们的地址是 127.0.0.1 ,支付宝回调,只能回调公网地址,调不回我们这,我们收不到支付宝的回调--->解决方案:
1.使用公网ip部署项目
2.使用内网穿透
内网穿透文档:https://zhuanlan.zhihu.com/p/370483324
原理:转发-->支付宝向某个域名(随机生成)把请求发送给 花生壳 --->根据请求知道是哪台内网机器---->把网络请求,转发给你
视图类
from rest_framework.viewsets import ViewSet
from .models import Order
from utils.common_logger import logger
from rest_framework.response import Response
class SuccessView(ViewSet):
def get(self,request,*args,**kwargs):
...
def post(self,request,*args,**kwargs):
try:
result_data = request.data.dict() # 支付宝发送post请求给我们--->数据携带再请求体中--->urlencoded-->request.data不是字典格式,使用dict做成字典格式
out_trade_no = result_data.get('out_trade_no')
signature = result_data.pop('sign')
from libs.alipay_common import alipay
result = alipay.verify(result_data, signature) # 验签通过表示是支付宝给的,不是别人伪造的
# trade_status 确认订单付款成功了
if result and result_data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED"):
# 完成订单修改:订单状态、流水号、支付时间
Order.objects.filter(out_trade_no=out_trade_no).update(order_status=1)
# 完成日志记录
logger.warning('%s订单支付成功' % out_trade_no)
return Response('success') # 必须这样,不能有别的东西
else:
logger.error('%s订单支付失败' % out_trade_no)
except:
pass
return Response('failed')
wlguwg8538@sandbox.com
扫码登陆功能
逻辑
1.网站上,点击扫码登录---->弹出二维码
向后端发送请求---->后端生成二维码--->返回--->前端显示了--->放了个链接地址
2.掏出手机,打开对应的app---->扫描二维码---->app能解析出这个地址---->取出你当前app登录的token---->向这个地址发送请求,携带token
后端有个携带token请求登录的接口
后端接口:拿到请求传入的token,解析出当前用户---->签发token---->找个地方存着
3.网站上,开启了定时任务,不停的向后端发送请求---->查询有没有我让它签发token
一旦发现没有,过一会在发,3分钟内不停的发
一旦发现有,携带回来---》token---》前端就登录成功了
3.后端接口
1.生成二维码接口
2.手机携带token,得到用户,再签发token的接口
3.网站获取token接口
4.前端
1.二维码页面
2.定时任务
真实逻辑
1.前端
1.进入扫码登录页面---->向后端发送请求,获取一个验证码图片,显示在前端
把key:1234567暂存
2.掏出手机扫码--->用自己的app--->扫码--->app端提示是否登录--->当你点登录--->向二维码链接地址发送请求--->http://192.168.1.252:8000/api/v1/user/qrlogin/login/?key=1234567&token=sss
3.启动定时任务,隔一会向后端发送一个查询是否登录的请求--->
http://192.168.1.252:8000/api/v1/user/check_login/?key=123456
4.根据key,有没有签发的token,如果有直接带回来,token,username--->登录成功了
如果没有,过一会在发,5分钟以后就不做了
2.后端
1.获取验证码图片接口--->验证码图片放链接地址:http://192.168.1.252:8000/api/v1/user/qrlogin/login/?key=123456,图片的地址中也有这个key {url:base64,key:123456}
-http://192.168.1.252:8000/api/v1/user/qrlogin/login/?user_id=1&key=1234567
2.扫码登录接口---->取出用户的token,认证---->根据当前用户签发token--->根据放在某个位置待命---{123456唯一:value}
3.查询是否签发token的接口,根据key
后端
from rest_framework.viewsets import ViewSet
import qrcode
from io import BytesIO
import base64
from rest_framework_jwt.settings import api_settings
from django.core.cache import cache
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
class QRlogin(ViewSet):
@action(methods=['GET'],detail=False)
def scan(self,request,*args,**kwargs):
img = qrcode.make('http://127.0.0.1:8000/api/v1/user/qrlogin/login/?user_id=1')
img = img.get_image()
b= BytesIO()
img.save(b,format="JPEG")
res = base64.b64encode(b.getvalue())
return APIResponse(url=res,user_id = 1)
@action(methods=['POST'],detail=False)
def login(self,request,*args,**kwargs):
user_id = request.query_params.get('user_id')
user = User.objects.get(pk= user_id)
# 签发token,放到redis
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
user_info={"username":user.username,"token":token}
import time
time.sleep(5)
cache.set('user_id_%s' % user_id, user_info)
return APIResponse()
@action(methods=['GET'], detail=False)
def check_login(self,requests,*args,**kwargs):
user_id = requests.GET.get('user_id')
user_info = cache.get('user_id_%s' % user_id)
if user_info:
cache.set('user_id_%s' % user_id, None)
return APIResponse(token=user_info.get('token'), username=user_info.get('username'))
else:
return APIResponse(code=101, msg='手机端尚未确认登录')
路由
from django.urls import path
from .views import UserView,RedisTest,SetPassword,SckillView,QRlogin
from rest_framework.routers import SimpleRouter
from rest_framework_jwt.views import obtain_jwt_token
router = SimpleRouter()
router.register('userinfo',UserView,'userinfo')
router.register('setpassword',SetPassword,'setpassword')
router.register('qrlogin',QRlogin,'qrlogin')
urlpatterns = [
# path('test/',RedisTest.as_view())
path('skill/',SckillView.as_view())
]
urlpatterns +=router.urls
前端
<template>
<div>
<img :src="url" alt="">
</div>
</template>
<script >
import el from "element-ui/src/locale/lang/el";
export default {
data(){
return{
url:'',
user_id: '',
t:null
}
},
created() {
this.$axios.get(`${this.$settings.BASE_URL}user/qrlogin/scan/`).then(res=>{
if (res.data.code==100){
//打开二维码,扫码login,开定时器
this.url ='data:image/jpg;base64,'+ res.data.url
this.user_id = res.data.user_id
//开启定时任务
this.t = setInterval(()=>{
this.$axios.get(`${this.$settings.BASE_URL}user/qrlogin/check_login/?user_id=`+this.user_id).then(res=>{
if (res.data.code==100){
this.$cookies.set('token',res.data.token,'7d')
this.cookies.set('username',res.data.username,'7d')
clearInterval(this.t)
this.t = null
this.$router.push('/')
}else{
this.$message({
message: res.data.msg,
type: 'warning'
});
}
})
},3000)
}
})
}
}
</script>
<style scoped>
</style>
阿里云购买
1.购买一台服务
1.项目跑在服务器上
2.购买公网ip:别人访问我们的ip,就能访问到我们的项目
3.购买域名:备案--->访问域名--->转发到你的ip
2.阿里云,华为云,腾讯云
按量付费--->冲100块--->买4台
阿里云云服务器:https://ecs.console.aliyun.com/home
3.下载 finalshell(xshell收费) ,远程链接linux服务器的
http://www.hostbuf.com/t/988.html
不下这个软件:打开cmd :ssh root@8.130.18.221 输入密码
一堆linux命令
上线前准备
后端项目
修改好线上配置文件,把代码推送到git仓库
1.将配置文件中的dev.py内容复制到prod.py
2.修改配置文件内容
1.修改debug模式
DEBUG = False
ALLOWED_HOSTS = ['*']
2.修改前台基URL,后台基URL
LUFFY_URL = 'http://47.111.10.23' # 47.111.10.23是在阿里云服务器上购买的公网ip地址
BACKEND_URL="http://47.111.10.23:8000"
3.代码推送到git仓库
前端项目
1.修改前端访问的后端地址
export default {
BASE_URL:'http://47.111.10.23:8000/api/v1/'
}
2.把vue项目编译成 html,css,js
1.命令:npm run build # 在项目目录下生成dist文件夹,内部就是咱们上线要用的
2.把dist文件夹压缩,待命
wlguwg8538@sandbox.com
上线架构图
购买服务器
1.购买阿里云服务器
2.短期或是测试使用,创建 按量收费 服务器,可以随时删除,删除后不再计费,但要保证账户余额100元以上
连接服务器
1.账号
ssh root@47.111.10.23
2.密码
>: ********
服务器命令
管理员权限
1)以下所有的服务器命令均可以在管理员权限下执行
>: sudo 命令
配置终端
1)编辑配置文件
>: vim ~/.bash_profile
2)将原来内容全部删除掉
>: ggdG
3)进入编辑状态:填入下方两行
>: i
export PATH=$PATH:$HOME/bin
PS1='Path:\w\n>:'
4)退出编辑状态
>: esc
5)保存修改并退出
>: :wq
6)生效配置
>: source ~/.bash_profile
安装git
更新系统软件包
>: yum update -y
1.方式一:
yum install git -y
2.方式二:(开发会用的软件)
yum -y groupinstall "Development tools"
3.执行下面这条
yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel psmisc libffi-devel -y
4.检测是否成功:会将git作为依赖安装号:
git
安装mysql
安装mysql 5.7
2.前往用户根目录
cd ~
3.下载mysql57
wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm
4.安装mysql57
yum -y install mysql57-community-release-el7-10.noarch.rpm
yum install mysql-community-server --nogpgcheck -y
5.启动mysql57并查看启动状态
systemctl start mysqld
systemctl status mysqld
6.查看默认密码并登录
grep "password" /var/log/mysqld.log # ,3QRakjs+EU/
mysql -uroot -p
7.修改密码
ALTER USER 'root'@'localhost' IDENTIFIED BY 'Lqz12345?';
安装redis
官方下载编译好的reids
1.下载
wget https://packages.redis.io/redis-stack/redis-stack-server-6.2.6-v7.rhel7.x86_64.tar.gz
2.解压安装包
tar -xf redis-stack-server-6.2.6-v7.rhel7.x86_64.tar.gz
3.移动到redis
mv redis-stack-server-6.2.6-v7/ redis
4.切换到redis下的bin文件夹
cd redis/bin
5.启动redis
./redis-server # 启动redis,使用默认配置启动的
2.需求:在任意路径下敲redis-server都能把服务运行,
1.方式一:把bin路径加入到环境变量
2.方式二:使用软连接-->/usr/bin/本身在环境变量,在任意路径敲redis-server redis-cli都能找到
ln -s /root/redis/bin/redis-server /usr/bin/redis-server
ln -s /root/redis/bin/redis-cli /usr/bin/redis-cli
2.1 查看是否创建软连接成功
ls |grep redis
2.2 启动redis服务,后台运行
redis-server &
源码安装
1.下载redis-6.2.6
wget http://download.redis.io/releases/redis-6.2.6.tar.gz
2.解压安装包
tar -xf redis-6.2.6.tar.gz
3.进入目标文件
cd redis-6.2.6
4.编译环境gcc,在src路径下把源码编译出redis-cli、reidis-server
make
5.复制环境到指定路径完成安装
cp -r ~/redis-6.2.6 /usr/local/redis
6.配置redis可以后台启动:修改下方内容
vim /usr/local/redis/redis.conf
daemonize yes
7.完成配置修改
>: esc
>: :wq
8.建立软连接
ln -s /usr/local/redis/src/redis-server /usr/bin/redis-server1
ln -s /usr/local/redis/src/redis-cli /usr/bin/redis-cli1
9.后台运行redis
>: cd /usr/local/redis
>: redis-server1 ./redis.conf
10.测试redis环境
redis-cli
11.关闭redis服务
pkill -f redis -9
redis-cli shutdown
安装python
1.安装python
1.可以使用yum 安装,不能指定版本
2.源码安装,下载指定版本的源码,编译安装
3.所有linxu和mac,都自带python2:系统服务,是用python写的
4.阿里云的centos默认装了python3.6.8
5.python2.7 python3.6.8 python3.9
1.源码安装python,依赖一些第三方zlib* libffi-devel
yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel psmisc libffi-devel zlib* libffi-devel -y
1.前往用户根目录
cd ~
2.下载 或 上传 Python3.8.6 服务器终端
# https://registry.npmmirror.com/binary.html?path=python/
# wget https://registry.npmmirror.com/-/binary/python/3.8.6/Python-3.8.6.tgz
wget https://registry.npmmirror.com/-/binary/python/3.9.10/Python-3.9.10.tgz
# wget https://www.python.org/ftp/python/3.9.16/Python-3.9.16.tgz
3.解压安装包
tar -xf Python-3.9.10.tgz
4.进入目标文件
cd Python-3.9.10
5.配置安装路径:/usr/local/python3
把python3.9.10 编译安装到/usr/local/python38路径下
./configure --prefix=/usr/local/python39
6.编译并安装,如果报错,说明缺依赖
yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel psmisc libffi-devel zlib* libffi-devel -y
7.make && make install
7.建立软连接:/usr/local/python38路径不在环境变量,终端命令 python3,pip3
ln -s /usr/local/python39/bin/python3 /usr/bin/python3.9
ln -s /usr/local/python39/bin/pip3 /usr/bin/pip3.9
8.机器上有多个python和pip命令,对应关系如下
python 2.x pip
python3 3.6 pip3
python3.9 3.9 pip3.9
#8 删除安装包与文件:
rm -rf Python-3.9.10
rm -rf Python-3.9.10.tar.xz
安装虚拟环境
1.安装依赖
pip3.9 install virtualenv
# python3.9 -m pip install --upgrade pip
# python3.9 -m pip install --upgrade setuptools
# pip3.9 install pbr
>: pip3.9 install virtualenvwrapper
"""
cd /usr/local/python39/bin
ls
>>>virtualenv
"""
2.建立虚拟环境软连接
>: ln -s /usr/local/python39/bin/virtualenv /usr/bin/virtualenv
3.配置虚拟环境:填入下方内容
# ~/ 表示用户家路径:root用户,就是在/root/.bash_profile
>: vi ~/.bash_profile
# 按 a
# 光标上下控制,粘贴上下面内容
VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3.9
source /usr/local/python39/bin/virtualenvwrapper.sh
# 按 esc
# 输入 :wq 敲回车
# 退出编辑状态
esc
# 保存修改并退出
>: :wq
4.更新配置文件内容
source ~/.bash_profile
5.虚拟环境默认根目录:/root/.virtualenvs
6.创建虚拟环境
mkvirtualenv -p python3.9 luffy
安装uwsgi
1.django项目上线需要使用uwsgi这个web服务器运行django项目,安装这个web服务器
2.使用uwsgi运行django,不再使用测试阶段的wsgiref来运行django了
3.uwsgi是符合wsgi协议的web服务器,使用c写的性能高,上线要使用uwsgi
4.安装步骤
1.在真实环境下安装
pip3.9 install uwsgi
ps:安装到了python39的安装路径的bin路径下了
"""
cd /usr/local/python39/bin
ls
>>>uwsgi
"""
2.建立软连接
ln -s /usr/local/python39/bin/uwsgi /usr/bin/uwsgi
安装nginx
1.反向代理服务器
1.做请求转发
2.静态资源代理
3.负载均衡
1.前往用户根目录
cd ~
2.下载nginx1.13.7
wget http://nginx.org/download/nginx-1.13.7.tar.gz
3.解压安装包
tar -xf nginx-1.13.7.tar.gz
4.进入目标文件
cd nginx-1.13.7
5.配置安装路径:/usr/local/nginx
./configure --prefix=/usr/local/nginx
6.编译并安装
make && make install
7.建立软连接:终端命令 nginx
ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx
8.删除安装包与文件:
cd ~
rm -rf nginx-1.13.7
rm -rf nginx-1.13.7.tar.xz
9.测试Nginx环境,服务器运行nginx,本地访问服务器ip
nginx # 启动nginx服务,监听80端口---->公网ip 80 端口就能看到页面了
服务器绑定的域名 或 ip:80
"""
http://47.111.10.23/----->不写默认80端口
"""
10.静态文件放的路径:/usr/local/nginx/html
11.查看进程
ps aux | grep nginx
部署前端项目
1.dist.zip 文件,在本地,上传到远程服务器
## html文件中
1.在远程服务器上
yum install lrzsz -y # 跟本地机器上传下载的软件
yum install unzip -y #解压zip软件
2.在远程服务器上
rz # 打开你本地的目录,选中dist.zip 上传到远端
"""
mac终端执行的不可上传到远端,输入以下(mac本地终端输入)
scp Desktop/dist.zip root@47.111.10.23:~
scp /path/to/example.txt username@remotehost:/home/username
例如,如果你要上传的文件是位于你的本地电脑的/path/to/example.txt,远程服务器的用户名是username,主机名或IP地址是remotehost,上传到远程服务器的目录是/home/username
"""
3.解压
unzip dist.zip
4.移动文件 /home/html 下面有咱们的前端静态文件
mv /root/dist /home/html
5.配置nginx 静态代理
cd /usr/local/nginx/conf # nginx.conf 配置文件
mv nginx.conf nginx.conf.bak
vi nginx.conf
# 按 a 粘贴下面代码
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
server {
listen 80;
server_name 127.0.0.1;
charset utf-8;
location / {
root /home/html;
index index.html;
try_files $uri $uri/ /index.html;
}
}
}
# 按 esc :wq 回车
6.重启nginx
nginx -s reload
部署后台项目
1.本地
1.prod.py 配置文件搞好,上午搞了
2.修改项目中wsgi.py,asgi.py 用uwsgi运行wsgi.py
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy_api.settings.prod')
3.导出项目依赖
pip3 freeze > requirements.txt
4.推到远端
2.远程服务器
1.拉取项目,安装模块
mkdir /home/project
cd /home/project
git clone https://gitee.com/luona-cx/luffy_api.git
2.进入到虚拟环境
workon luffy
cd /home/project/luffy_api
pip install -r requirements.txt # 可能会出错 mysqlclient装不上,先注释,装上能装上的,再单独装mysqlclient
yum install python3-devel -y
yum install mysql-devel --nogpgcheck -y
pip install mysqlclient
2.虚拟环境中也要安装uwsgi
pip install uwsgi
配置数据库
mysql -uroot -p
1.创建数据库
create database luffy default charset=utf8;
2.设置权限账号密码:账号密码要与项目中配置的一致
grant all privileges on luffy.* to 'luffy'@'%' identified by 'Luffy123?';
grant all privileges on luffy.* to 'luffy'@'localhost' identified by 'Luffy123?';
flush privileges;
3.退出mysql
quit;
4.使用本地navicate链接阿里云的luffy库,使用luffy用户
迁移表
1.把项目中得迁移文件删除,提交,远程
python manage.py makemigrations
python manage.py migrate
ps:在本地luffy中把apps中的migrations中的00x删除
"""
python manage_prod.py makemigrations
python manage_prod.py migrate
"""
uwsgi 运行django
1.写一个uwsgi的配置文件,在项目路径下,新建一个 luffyapi.xml
>>>vi luffyapi.xml
<uwsgi>
<socket>127.0.0.1:8888</socket>
<chdir>/home/project/luffy_api/</chdir>
<module>luffy_api.wsgi</module>
<processes>4</processes>
<daemonize>uwsgi.log</daemonize>
</uwsgi>
2.使用uwsgi启动
uwsgi -x luffyapi.xml
3.查看是否正常运行
ps aux |grep uwsgi
4.补充
以下是uwsgi与nginx的通信手段,三选一即可
1.选项1, 使用unix socket与nginx通信,仅限于uwsgi和nginx在同一主机上情形
Nginx配置中uwsgi_pass应指向同一socket文件
socket=/run/uwsgi/%(project).sock
2.选项2,使用TCP socket与nginx通信
Nginx配置中uwsgi_pass应指向uWSGI服务器IP和端口
socket=0.0.0.0:8888 或则 socket=:8000
3.选项3,使用http协议与nginx通信
Nginx配置中proxy_pass应指向uWSGI服务器一IP和端口
http=0.0.0.0:8888
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8888;
uwsgi_param UWSGI_SCRIPT luffy_api.wsgi;
uwsgi_param UWSGI_CHDIR /home/project/luffy_api/; # 用选项1,2,接收不了http请求,性能高,更接近于底层
proxy_pass http://127.0.0.1:8888; # # 用选项3
}
补充:127.0.0.1与0.0.0.0区别
1.软件运行,监听地址
127.0.0.1:只能访问 127.0.0.1 localhost ,不能用本机ip地址访问,外部所有人都不能 访问你
0.0.0.0:127.0.0.1 localhost 本机ip地址访问 同一个局域网内,都可以通过ip地址访问
2.本地host解析
输入网址---》www.baidu.com---->找本地host文件---》找跟ip地址的对应关系----》找到直接访问这个ip地址----如果找不到---->用你配置的dns解析
配置nginx转发
1.
cd /usr/local/nginx/conf
vi nginx.conf
2.新增的server
server {
listen 8000;
server_name 127.0.0.1;
charset utf-8;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8888;
uwsgi_param UWSGI_SCRIPT luffy_api.wsgi;
uwsgi_param UWSGI_CHDIR /home/project/luffy_api/;
}
}
3.重启nginx
` nginx -s reload
导入数据
1.此处为了简便,将原来的数据,直接转储sql文件(结构和数据)
2.将远程的luffy数据库直接运行sql文件
ps:实际上,是直接添加数据
配置域名解析
购买
配置后台admin访问
1.浏览器访问http://47.111.10.23:8000/admin 发现没有样式
因为uwsgi不能给我们代理静态资源--->debug =False--->不能转发静态资源了
收集静态资源,使用nginx代理
2.prod.py中加入
"""
cd /home/project/luffy_api/luffy_api/settings
vi prod.py
"""
STATIC_ROOT = '/home/project/luffy_api/luffy_api/static/'
3.执行命令
1.进入虚拟环境
mkdir /home/project/luffy_api/luffy_api/static
python manage_prod.py collectstatic
"""
cd /home/project/luffy_api/luffy_api/static
ls
>>>admin rest_framework
"""
2.修改nginx配置文件
cd /usr/local/nginx/conf
vi nginx.conf
3.新增的配置静态文件
server {
listen 8000;
server_name 127.0.0.1;
charset utf-8;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8888;
uwsgi_param UWSGI_SCRIPT luffy_api.wsgi;
uwsgi_param UWSGI_CHDIR /home/project/luffy_api/;
}
location /static {
alias /home/project/luffy_api/luffy_api/static;
}
}
4.重启nginx
nginx -s reload
安全组
1.买的阿里云机器80,3306,8000 端口开放的
2.但是,3306,6379 8000端口可能没打开
3.不打开安全组的端口,是访问不进来的