当前位置: 首页 > article >正文

前:vue 后:django 部署:supervisor+nginx 流程及部分问题简记

文章目录

    • 前:vue 后:django 部署:supervisor+nginx 流程及部分问题简记
      • 一、服务器环境准备
      • 二、后端 django部署
      • 三、nginx处配置
          • ps:补充一个问题:如有涉及文件上传,nginx处还需配置,之前在本地测无问题,部署后上传失败,简记流程

前:vue 后:django 部署:supervisor+nginx 流程及部分问题简记

一、服务器环境准备

安装必要的软件:

sudo apt update && sudo apt install -y python3-pip python3-venv supervisor

如果是 CentOS:

sudo yum install -y python3-pip python3-venv supervisor

检查是否安装成功:

python3 --version
pip3 --version
supervisord --version

二、后端 django部署

克隆项目至服务器本地:

cd /data
git clone https://github.com/your-repo/django-project.git
cd django-project

创建 Python 虚拟环境:

python3 -m venv venv
source venv/bin/activate

# 安装依赖
pip install --upgrade pip
pip install -r requirements.txt

安装gunicorn:

pip install gunicorn

# 测试运行 Gunicorn
gunicorn --workers 3 --bind 0.0.0.0:8000 django-project.wsgi:application

配置Supervisor:
在项目文件夹下创建 supervisord.d 文件夹,下创建django-project-wsgi.ini

[program:django-project-wsgi]
directory = /data/gitcode/django-project
command = /data/gitcode/django-project/venv/bin/gunicorn -w4 -b 0.0.0.0:8000 django-project.wsgi --timeout 1800 --keep-alive 30
numprocs = 1
autostart = true
autorestart = true
redirect_stderr = true
stdout_logfile = /data/gitcode/logs/django-project.log
stderr_logfile = /data/gitcode/logs/django-project_err.log

可以在该项目文件夹下创建启动的shell脚本:

#!/bin/bash
sudo supervisorctl restart django-project-wsgi

三、nginx处配置

server {
        listen       8082;
        server_name  【服务器IP】;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html/dist; # 前端vue打包的dist放置位置
            index  index.html index.htm;
         	try_files $uri $uri/ /index.html;
        }
		location /api/ {
		    proxy_pass http://【服务器IP】:8000;
		}
		location @router {
            rewrite ^.*$ /index.html last;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

可写一个shell脚本重启:

sudo systemctl restart nginx
sudo /usr/local/nginx/sbin/nginx -s reload
sudo chmod -R 777 /usr/local/nginx/html/dist
ps:补充一个问题:如有涉及文件上传,nginx处还需配置,之前在本地测无问题,部署后上传失败,简记流程

vue:

<template>
  <Card style="width: 100%; height: 115%">
    <div>
      <Upload
        :before-upload="beforeUpload"
        :on-success="handleSuccess"
        :on-error="handleError"
        accept=".csv"
      >
        <Button type="primary">上传 CSV 文件</Button>
      </Upload>
      <div style="height: 10px"></div>
      <Alert show-icon>
        已上传文件: <span>{{ uploadedFileName }}</span>
      </Alert>
      <div v-if="duplicates.length > 0">
        <Alert show-icon type="warning">
          重复的 MAC 地址 <b>({{ duplicates.length }})</b>:
          <Scroll :height="400">
            <ul>
              <li v-for="mac in duplicates" :key="mac">{{ mac }}</li>
            </ul>
          </Scroll>
        </Alert>
        <Button type="success" @click="downloadDuplicates">下载重复的 MAC 地址</Button>
      </div>
      <div v-else>
        <Alert show-icon type="success">
          没有重复的 MAC 地址
        </Alert>
      </div>
    </div>
  </Card>
</template>

<script>
import { Upload, Button, Alert, Card, Scroll } from 'iview';
import axios from 'axios';

export default {
  components: {
    Upload,
    Button,
    Alert,
    Card,
    Scroll
  },
  data() {
    return {
      uploadedFileName: '',
      duplicates: []
    };
  },
  methods: {
    beforeUpload(file) {
      this.uploadedFileName = file.name;
      const formData = new FormData();
      formData.append('file', file);
      axios.post('/api/upload-csv/', formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      })
      .then(response => {
        this.handleSuccess(response);
      })
      .catch(error => {
        this.handleError(error);
      });
      return false; // Prevent default upload behavior
    },
    handleSuccess(response) {
      this.$Message.success('文件上传成功');
      this.duplicates = response.data.duplicates;
    },
    handleError(error) {
      this.$Message.error('文件上传失败');
    },
    downloadDuplicates() {
      const blob = new Blob([this.duplicates.join(', ')], { type: 'text/plain' });
      const url = window.URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = 'duplicates.txt';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      window.URL.revokeObjectURL(url);
    }
  }
};
</script>

<style scoped>
.custom-bread-crumb {
  margin-bottom: 20px;
}
</style>
export const uploadCsvFile = (file, token) => {
  const formData = new FormData();
  formData.append('file', file);

  return axios.request({
    url: '/api/upload-csv/',
    method: 'post',
    headers: {
      'Authorization': `Token ${token}`,
      'Content-Type': 'multipart/form-data'
    },
    data: formData
  })
}

django views.py

UPLOAD_FOLDER = 'uploads'
if not os.path.exists(UPLOAD_FOLDER):
    os.makedirs(UPLOAD_FOLDER)

class HandleNacMultipulRecords(APIView):

    def post(self, request):
        if 'file' not in request.FILES:
            return Response({'error': 'No file part'}, status=status.HTTP_400_BAD_REQUEST)
        file = request.FILES['file']
        if file.name == '':
            return Response({'error': 'No selected file'}, status=status.HTTP_400_BAD_REQUEST)

        if file.name.endswith('.csv'):
            file_path = os.path.join(UPLOAD_FOLDER, file.name)
            with open(file_path, 'wb+') as destination:
                for chunk in file.chunks():
                    destination.write(chunk)

            # 解析 CSV 文件并提取 MAC Address 列
            mac_addresses = []
            with open(file_path, newline='', encoding='utf-8') as csvfile:
                csv_reader = csv.DictReader(csvfile)
                for row in csv_reader:
                    mac_addresses.append(row['MAC Address'])

            # 删除上传的文件
            # os.remove(file_path)
            # 验证 MAC 地址格式
            valid_mac_addresses = [mac for mac in mac_addresses if
                                   re.match(r'^([0-9A-Fa-f]{2}){5}[0-9A-Fa-f]{2}$', mac)]
            mac_counter = Counter(valid_mac_addresses)
            duplicates = [mac for mac, count in mac_counter.items() if count > 1]
            logger.info(duplicates)

            return Response({
                'message': 'File uploaded successfully',
                'valid_mac_addresses': valid_mac_addresses,
                'duplicates': duplicates
            }, status=status.HTTP_200_OK)

        return Response({'error': 'Invalid file type'}, status=status.HTTP_400_BAD_REQUEST)
http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;
    client_max_body_size 100M; # 注意:这里需设置,否则会上传失败!

    #gzip  on;
    include /usr/local/nginx/conf/conf.d/*.conf;
    ...

http://www.kler.cn/a/582901.html

相关文章:

  • python编写的一个打砖块小游戏
  • 基于AI智能算法的无人机城市综合治理
  • 计算机操作系统(一) 什么是操作系统
  • 安卓应用架构模式 MVC MVP MVVM有什么区别?
  • 多云环境中的大数据部署:从挑战到最佳实践
  • Vscode工具开发Vue+ts项目时vue文件ts语法报错-红波浪线等
  • 关于Java的入门
  • 解锁 Postman:下载安装与账户注册使用的全攻略,踏上测试新征程
  • Java后端高频面经——计算机网络
  • hadoop第3课(hdfs shell常用命令)
  • word排版:段内公式由于固定行间距显露不出的问题
  • kafka + flink +mysql 案例
  • Linux NFS/TFTP文件系统挂载
  • C# 数据类型总结
  • Android ANR 监控方法与事件分发耗时优化实战
  • 无人机全景应用解析与技术演进趋势
  • 新能源汽车电控系统的大尺寸PCB需求:猎板PCB的技术突围
  • 【后端开发面试题】每日 3 题(十)
  • 笔记本电脑开机自动启用自定义电源计划方法
  • 11. Pandas :操作Excel文件(Excel报表的案例研究)