前后端分离项目部署学习-好课商城项目部署详细步骤-DjangoDRF+Vue+Nginx+Uwsgi

部署

  1. 静态文件

当Django运行在生产模式时,将不再提供静态文件的支持,需要将静态文件交给静态文件服务器。

我们先收集所有静态文件。项目中的静态文件除了我们使用的front_end_pc中之外,django本身还有自己的静态文件,如果rest_framework、xadmin、admin、ckeditor等。我们需要收集这些静态文件,集中一起放到静态文件服务器中。

我们要将收集的静态文件放到front_end_pc目录下的static目录中,所以先创建目录static。

Django提供了收集静态文件的方法。先在配置文件中配置收集之后存放的目录

STATIC_ROOT = os.path.join(os.path.dirname(os.path.dirname(BASE_DIR)), 'front_end_pc/static')

然后执行收集命令

python manage.py collectstatic

我们使用Nginx服务器作为静态文件服务器

2.Nginx服务器安装:

如果本机安装了nginx,卸载nginx
apt-get --purge autoremove nginx
检查本机是否还有nginx程序在后台运行,如果有直接kill掉
ps -ef | grep  nginx

默认版本安装
方便简单,很多依赖都自动给安装好了,一个命令即可 在root 用户下

apt-get update    # 更新包

如果在更新的时候下面没有公钥的的报错:

# 由于没有公钥,无法验证下列签名: NO_PUBKEY 9165938D90FDDD2E
则运行 下面的命令
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys  + NO_PUBKEY后面的公钥
比如:
#sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 9165938D90FDDD2E
最后重新 apt-get update
# 安装Nginx
apt-get install nginx

文件介绍

/usr/sbin/nginx:主程序,启动文件
/etc/nginx:存放配置文件
/var/www/html:存放项目目录
/var/log/nginx:存放日志   
一般自动安装配置文件目录和主程序目录不变,因为版本原因,其它目录可能会变,但是都可以从配置文件里ngxin.conf里找到对应的位置。


在浏览器(Ubuntu里面的)里面访问127.0.0.1:80  显示Nginx安装成功就可以了

打开Nginx的配置文件

进入root用户:
sudo su
pythonvip


sudo vim /etc/nginx/nginx.conf

在server部分中配置(这里可暂时不去写,最后下面有完整的参照)

# 前端服务器配置
server {
         listen       8000; # 服务的端口号
         server_name  127.0.0.1;  # 服务的id

        location / {
             root   /home/python/Desktop/front_end_pc;  # 前端服务路径
             index  index.html index.htm;
         }

        # 余下省略
}

重启Nginx服务器

sudo /usr/sbin/nginx -s reload   重启Nginx

首次启动nginx服务器

sudo /usr/local/nginx/sbin/nginx

停止nginx服务器

sudo /usr/local/nginx/sbin/nginx -s stop
  1. 动态接口

在项目中复制开发配置文件dev.py 到生产配置prod.py

修改配置文件prod.py中

DEBUG = False

ALLOWED_HOSTS = [...,  'http://127.0.0.1:8000','http://127.0.0.1:8001']  # 添加

CORS_ORIGIN_WHITELIST = (
    .....
    #添加
    'http://127.0.0.1:8000',
    'http://127.0.0.1:8001',
    'http://127.0.0.1:8002',
   
    
)

修改wsgi.py文件

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "meiduo_mall.settings.prod")

django的程序通常使用uwsgi服务器来运行

3安装uwsgi

在当前项目的虚拟环境中安装:

pip install uwsgi

在项目目录/好课_mall 下创建uwsgi配置文件 uwsgi.ini 该文件与manage.py同级目录

[uwsgi]
#使用nginx连接时使用,Django程序所在服务器地址
socket=192.168.1.107:8002    # 该 ip可以是服务器的地址 这里我们用Ubuntu的地址和ip
#直接做web服务器使用,Django程序所在服务器地址
#http=10.211.55.2:8001     # 这里是用做uwsgi与Django通信是否注册的时候使用的,一般在Nginx访问后端后端的接口报错的时候可以使用,一般很少用
#项目目录
chdir=/home/pyvip/hualong/haoke_mall
#项目中wsgi.py文件的目录,相对于项目目录
wsgi-file=haoke_mall/wsgi.py
# 进程数
processes=4
# 线程数
threads=2
# uwsgi服务器的角色
master=True
# 存放进程编号的文件
pidfile=uwsgi.pid
# 日志文件,因为uwsgi可以脱离终端在后台运行,日志看不见。我们以前的runserver是依赖终端的
# 方便查看报错信息的
daemonize=uwsgi.log
# 指定依赖的虚拟环境
virtualenv=/home/pyvip/.virtualenvs/hualong
# 最大运行内存 
buffer-size = 65536

启动uwsgi服务器:在 uwsgi.ini 目录下

uwsgi --ini uwsgi.ini

注意如果想要停止服务器,除了可以使用kill命令之外,还可以通过

uwsgi --stop uwsgi.pid

注意:

uwsgi --ini uwsgi.ini  启动后会生成 uwsgi.log  这个里面一定要记得去看看 ,启动是否成功,端口号是否被占用等情况  比如: 192.168.1.107:8002  已存在 则是8002被占用了
可以用命令杀掉这个端口在重启:
比如:  记得执行2次
sudo fuser -k 8002/tcp

修改Nginx配置文件,让Nginx接收到请求后转发给uwsgi服务器

user root;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
http {
        # 使css文件正常加载
        include       mime.types;
        default_type  application/octet-stream;
        upstream haoke111 {
                 server 192.168.1.101:8002;
     }

    # 后端的ip配置
     server {
         listen  8001;
         server_name 127.0.0.1;
         charset utf-8;


         location / {
             include uwsgi_params ;
             uwsgi_pass haoke111;
         }

        location /static {
               alias /home/pyvip/hualong/front_end_pc/static;
        }
     }
     # 前端的服务配置
     server {
         listen       8000;

         server_name  127.0.0.1;

         #charset koi8-r;

         #access_log  logs/host.access.log  main;
         location /admin {
             include uwsgi_params;
             uwsgi_pass haoke111;
         }

         location /ckeditor {
             include uwsgi_params;
             uwsgi_pass haoke111;
         }

         location / {
             root   /home/pyvip/hualong/front_end_pc;
             index  index.html index.htm;
         }
        # 使css文件正常加载
        location ~.*(js|css|png|gif|jpg|mp3|ogg)$ {
                        root /home/pyvip/hualong/front_end_pc/;
                }


         error_page   500 502 503 504  /50x.html;
         location = /50x.html {
             root   html;
         }

        }
}
events {
            worker_connections  1024;    #nginx的最大并发访问量
            use epoll;    #异步IO
        }

重启nginx

sudo /usr/sbin/nginx -s reload   重启Nginx
如果出现 :nginx: [error] open() “/run/nginx.pid” failed (2: No such file or directory)
则执行:
sudo nginx -c /etc/nginx/nginx.conf 
然后再重启
sudo /usr/sbin/nginx -s reload 

prod.py

"""
Django settings for haoke_mall project.

Generated by 'django-admin startproject' using Django 3.1.10.

For more information on this file, see
https://docs.djangoproject.com/en/3.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.1/ref/settings/
"""
import datetime
from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# 添加导包路径
import sys
import os
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))


STATIC_ROOT = os.path.join(os.path.dirname(os.path.dirname(BASE_DIR)), 'front_end_pc/static')

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/

# 由于没有公钥,无法验证下列签名: NO_PUBKEY 9165938D90FDDD2E
# sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 9165938D90FDDD2E
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '8l7jsblq%pndqi1tzh*lc#k6mq=w8xqriv5q2ivxqr2aqdap4c'


"""
/usr/sbin/nginx:主程序,启动文件
/etc/nginx:存放配置文件
/var/www/html:存放项目目录
/var/log/nginx:存放日志  
sudo /usr/sbin/nginx   启动Nginx
sudo /usr/sbin/nginx  -s stop  停止


"""


# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False

ALLOWED_HOSTS = ['*','http://127.0.0.1:8002','http://127.0.0.1:8001','http://127.0.0.1:8000','http://127.0.0.1:80','http://192.168.1.101:8000','http://192.168.1.101:8001']


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'users',
    'verifications',
    'corsheaders',
    #
    'areas',
    'goods',
    'contents',
    # 注册富文本编辑器
    'ckeditor',  # 富文本编辑器
    'ckeditor_uploader',  # 富文本编辑器上传图片模块
    'django_crontab', # 定时任务
    'haystack',
    'carts',
    'orders',
    'payment',
]

# 支付宝配置
ALIPAY_APPID = "2016101300672735"
ALIPAY_URL = "https://openapi.alipaydev.com/gateway.do"
ALIPAY_DEBUG = True
# 账号: yuhiao9778@sandbox.com
# 密码:111111
# Haystack
HAYSTACK_CONNECTIONS = {
    'default': {
        'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
        'URL': 'http://192.168.1.101:9200/',  # 此处为elasticsearch运行的服务器ip地址,端口号固定为9200
        'INDEX_NAME': 'haoke',  # 指定elasticsearch建立的索引库的名称
    },
}

# 当添加、修改、删除数据时,自动生成索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

# 定时任务
CRONJOBS = [
    # 每5分钟执行一次生成主页静态文件
    ('*/1 * * * *', 'contents.crons.generate_static_index_html', '>> /home/pyvip/hualong/haoke_mall/log/crontab.log')
]
# 解决crontab中文问题
CRONTAB_COMMAND_PREFIX = 'LANG_ALL=zh_cn.UTF-8'
# 富文本编辑器ckeditor配置
CKEDITOR_CONFIGS = {
    'default': {
        'toolbar': 'full',  # 工具条功能
        'height': 300,  # 编辑器高度
        # 'width': 300,  # 编辑器宽
    },
}
CKEDITOR_UPLOAD_PATH = ''  # 上传图片保存路径,使用了FastDFS,所以此处设为''

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

# CORS
CORS_ORIGIN_WHITELIST = (
    'http://192.168.110.215:8002',
    'http://127.0.0.1:8080',
    'http://127.0.0.1:8081',
    'http://127.0.0.1:8000',
    'http://127.0.0.1:8001',
    'http://127.0.0.1:8002',
    'http://127.0.0.1:80',
    'http://0.0.0.0:9000',
    'http://0.0.0.0:8000',
    'http://0.0.0.0:8001',
    'http://0.0.0.0:8002',
    # 'localhost',
    'http://192.168.222.1:8080',
    'http://192.168.1.101:8002',
    'http://192.168.1.101:8001',
    'http://192.168.1.101:8000',
    'http://api.meiduo.site',

)
CORS_ALLOW_CREDENTIALS = True  # 允许携带cookie

# HWFZCXBBLTRBVYOG

# 以下是邮件配置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.163.com'
EMAIL_PORT = 25
#发送邮件的邮箱
EMAIL_HOST_USER = 'yike120@163.com'
#在邮箱中设置的客户端授权密码
EMAIL_HOST_PASSWORD = 'DZWFXIWBGFSYSDHZ'
#收件人看到的发件人
EMAIL_FROM = '好课商城<yike120@163.com>'


REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
    # 异常处理
    'EXCEPTION_HANDLER': 'haoke_mall.utils.exceptions.exception_handler',
    # 分页
    'DEFAULT_PAGINATION_CLASS': 'haoke_mall.utils.pagination.StandardResultsSetPagination',

}

JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'users.utils.jwt_response_payload_handler',
}

AUTHENTICATION_BACKENDS = [
    'users.utils.UsernameMobileAuthBackend',
]


ROOT_URLCONF = 'haoke_mall.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR,'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'haoke_mall.wsgi.application'

AUTH_USER_MODEL = 'users.User'
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': '127.0.0.1',  # 数据库主机
        'PORT': 3306,  # 数据库端口
        'USER': 'root',  # 数据库用户名
        'PASSWORD': 'qwe123',  # 数据库用户密码
        'NAME': 'hualong'  # 数据库名字
    }
}
CACHES = {

    "verify_codes": {   # 存储验证码
            "BACKEND": "django_redis.cache.RedisCache",
            "LOCATION": "redis://127.0.0.1:6379/2",
            "OPTIONS": {
                "CLIENT_CLASS": "django_redis.client.DefaultClient",
            }
    },
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/0",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
    "session": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
    "history": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/3",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
    "cart": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/4",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
}
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "session"

# Password validation
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators


# DRF扩展
REST_FRAMEWORK_EXTENSIONS = {
    # 缓存时间
    'DEFAULT_CACHE_RESPONSE_TIMEOUT': 60 * 60,
    # 缓存存储
    'DEFAULT_USE_CACHE': 'default',
}



# django文件存储
DEFAULT_FILE_STORAGE = 'haoke_mall.utils.fastdfs.fdfs_storage.FastDFSStorage'

# FastDFS
FDFS_URL = 'http://192.168.1.101:8888/'
FDFS_CLIENT_CONF = os.path.join(BASE_DIR, 'utils/fastdfs/client.conf')


# 生成的静态html文件保存目录
GENERATED_STATIC_HTML_FILES_DIR = os.path.join(os.path.dirname(os.path.dirname(BASE_DIR)), 'front_end_pc')

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/
LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_L10N = True

USE_TZ = True



# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/

STATIC_URL = '/static/'

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在debug模式下才输出日志
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {  # 日志处理方法
        'console': {  # 向终端中输出日志
            'level': 'INFO',
            '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/meiduo.log"),  # 日志文件的位置
            'maxBytes': 300 * 1024 * 1024,
            'backupCount': 10,
            'formatter': 'verbose'
        },
    },
    'loggers': {  # 日志器
        'django': {  # 定义了一个名为django的日志器
            'handlers': ['console', 'file'],  # 可以同时向终端与文件中输出日志
            'propagate': True,  # 是否继续传递日志信息
            'level': 'INFO',  # 日志器接收的最低日志级别
        },
    }
}

4.访问测试部署是否成功:

1.直接访问前端服务器的接口:127.0.0.1:8000  看看前端显示是否正常
2.访问127.0.0.1:8001 后端服务器是否正常返回数据  
3.没有问题后,访问127.0.0.1:8000  进行商品的购买操作,没有问题的话
4到此项目部署成功了
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本季程把开发知识拆解到项目里,让你在项目情境里学知识。这样的学习方式能让你保持兴趣、充满动力,时刻知道学的东西能用在哪、能怎么用。平时不明白的知识点,放在项目里去理解就恍然大悟了。  一、融汇贯通本视频采用了前后分离的开发模式,前使用Vue.js+Element UI实现了Web页面的呈现,后使用Python 的Django REST Framework框架实现了数据访问的接口,前通过Axios访问后接口获得数据。在学习完本章节后,真正理解前后的各自承担的工作。 二、贴近实战本程为学生信息管理系统程:Vue3 + Vite + ElementPlus + Django REST Framework项目实战 本季程主学生信息管理系统V5.0,内容包含:Django REST framework安装和项目初始化、数据的序列化、ViewSet视图集、DefaultRouter路由类、django-filter实现过滤、rest framework实现查找、rest framework实现分页、npm的使用、使用Vite构建vue3项目、Package.json解析、ElementPlus安装和应用、vue-router实现路由、使用Vuex的store对象、后台管理系统主界面的布局、axios组件的安装和请求、axios请求的模块化、请求拦截器和响应拦截器、使用el-select实现联级下拉、使用cascader实现联级选择、vue表单的验证、实现学生信息的添加、修改和删除、实现文件的上传等等功能 本案例完整的演示了项目实现过程,虽然不复杂,但涉及的内容非常多,特别是前后交互的时候,有诸多的坑等着你去踩,好在王老师全程代码呈现,带着大家一起填坑,大大提高学习效率的同时,也培养了大家良好的代码习惯,希望大家一起跟着王进老师学习Python开发。三、后续程预告:Vue和Django REST Framework实现JWT登录认证 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值