美文网首页
Django+Vue+Nginx开发和部署

Django+Vue+Nginx开发和部署

作者: xingxixi | 来源:发表于2021-06-18 14:05 被阅读0次

    概述

    开发采用前后端分离方式:
    1、后端采用Django框架开发,根据项目功能模块建立多个应用APP;
    2、前端以vue-element-admin为模板开发;
    3、部署采用Nginx+Docker方式。

    后端

    环境准备

    已安装python3.6.8环境和django库

    1、项目新建

    有两种方式:
    a、pycharm里直接创建:File-New Project-Django
    b、1)命令行创建一个Django项目:django-admin.py startproject 项目名
      2)创建一个APP:python manage.py startapp 应用名
      如创建多个APP,多次执行以上命令即可

    2、创建数据库

    a、编写models.py,创建数据模型

    from django.db import models
    
    # Create your models here.
    
    # 测试用例基本情况
    class Testcase(models.Model):
        # 如果没有models.AutoField,默认会创建一个id的自增列
        project = models.ForeignKey(to='pro.Project',on_delete=models.CASCADE,)  # 外键——所属项目
        name = models.CharField("测试用例名称", max_length=100)
        version = models.CharField("版本号", max_length=30)
        creator = models.CharField("创建者", null=True, max_length=30)
        create_time = models.DateTimeField("创建时间", null=True, auto_now_add=True)
        update_time = models.DateTimeField("更新时间", null=True, auto_now=True)
    

    注意:关联其他APP中的class为外键时,可用models.ForeignKey(to='pro.Project',on_delete=models.CASCADE,)
    b、创建数据库
     1、在settings.py文件中配置数据源:

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'tmp_dev',
            'USER': '***',
            'PASSWORD': '***',
            'HOST': '127.0.0.1',
            'PORT': '3306',
        }
    }
    

    2、按顺序执行以下命令:
      python manage.py migrate
      python manage.py makemigrations

    3、编写视图函数

    在每个APP的views.py文件里编写视图函数,不同APP里的model可相互引用。举例如下:

    # -*- coding: utf-8 -*-
    import sys,  json, datetime, math
    from django.http import JsonResponse
    from django.db.models import F,Q
    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    from .models import *
    import importlib
    import logging
    logger = logging.getLogger('A')
    importlib.reload(sys)
    # Create your views here.
    # 返回 projects 统计列表,以便渲染到所有项目的 projects 列表展示界面
    def get_projects(request):
        page = int(request.GET.get('page', 1))
        limit = int(request.GET.get('limit', 10))
        keyword = request.GET.get('keyword','')
        try:
            # print(page,limit,keyword)
            projects = Project.objects.filter(
                Q(name__icontains=keyword) |
                Q(status__icontains=keyword) |
                Q(project_leader__icontains=keyword)
            ).order_by('-status', '-update_time')
            total = projects.count()  # 不能用函数 len(),一旦用了函数 len(),projects_limit就不再是QuerySet数据类型,而是成了list数据类型
            if page >  math.ceil(total/limit):
                page = math.ceil(total/limit)
            paginator = Paginator(projects, limit)
            projects_limit = paginator.page(page).object_list
            projectpage = list(projects_limit.values(
                "id",
                "name",
                "abbr",
                "status",
                "project_leader",
                "product_leader",
            ))
        except PageNotAnInteger:
            projectpage=[]
        except EmptyPage:
            projectpage = []
        data = {
            "code": 20000,
            "data": {
                "page": page,
                "total": total,
                "items": projectpage
            }
        }
        logger.info('url: %s, method: %s, 返回所有项目的信息。' % (request.path, request.method))
        return JsonResponse(data, json_dumps_params={'ensure_ascii': False, 'indent': 2})
    
    4、配置路由

    在每个APP的urls.py文件里配置路由信息,路由必须与views.py里的函数对应,例如:

    from django.conf.urls import url
    import pro.views as views
    
    urlpatterns = [
        url(r'^get_pro_sel/$', views.get_pro_sel),
        url(r'^get_projects/$', views.get_projects),
        url(r'^get_project_basicinfo/$', views.get_project_basicinfo),
        url(r'^create/$', views.pro_create, name='pro_create'),
        url(r'^update/$', views.pro_update, name='pro_update'),
        url(r'^delete/$', views.pro_delete, name='pro_delete'),
    ]
    

    并在项目根目录下的urls.py里加入各APP模块里的url配置,例如:

    from django.contrib import admin
    from django.urls import path, include
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('tmp/pro/', include(('pro.urls','pro'),namespace='pro')),
        path('tmp/rep/', include(('rep.urls', 'rep'), namespace='rep')),
        path('tmp/tc/', include(('tc.urls','tc'),namespace='tc')),
        path('tmp/cod/', include(('cod.urls', 'cod'), namespace='cod')),
        path('tmp/bug/', include(('bug.urls', 'bug'), namespace='bug')),
        path('tmp/rbac/', include(('rbac.urls','rbac'),namespace='rbac')),
    ]
    
    5、启动服务器

    项目目录下运行命令:python manage.py runserver 127.0.0.1:8081

    前端

    vue-element-admin是一个后台前端解决方案,它基于vue和 element-ui实现。vue-admin-template是一个基础模板。本项目是在vue-admin-template的基础上进行了二次开发。

    环境准备

    1、安装Vue环境,参考Vue官网:https://cn.vuejs.org/v2/guide/
    2、element组件库:https://element.eleme.cn/#/zh-CN/component/installation
    3、分别下载vue-admin-template和vue-element-admin源码。
     vue-element-admin文档:https://panjiachen.github.io/vue-element-admin-site/zh/guide/
     vue-element-admin源码:https://github.com/PanJiaChen/vue-element-admin
     vue-admin-template源码:https://github.com/PanJiaChen/vue-admin-template

    1、运行vue-admin-template
    cd vue-element-admin
    #安装依赖
    npm install
    #启动项目
    npm run dev
    
    2、新增页面

    请参考vue-element-admin文档,有详细说明。

    3、前后端配置

    vue.config.js文件里配置前端访问地址和后端服务地址:

    const port = process.env.port || process.env.npm_config_port || 9000 // 9528 // dev port
    
    // All configuration item explanations can be find in https://cli.vuejs.org/config/
    module.exports = {
      /**
       * You will need to set publicPath if you plan to deploy your site under a sub path,
       * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
       * then publicPath should be set to "/bar/".
       * In most cases please use '/' !!!
       * Detail: https://cli.vuejs.org/config/#publicpath
       */
      publicPath: './',
      outputDir: 'dist',
      assetsDir: 'static',
      lintOnSave: process.env.NODE_ENV === 'development',
      productionSourceMap: false,
      devServer: {
        port: port,
        open: true,
        overlay: {
          warnings: false,
          errors: true
        },
        proxy: {
          '/tmp': {
            target: 'http://127.0.0.1:8081', //后端服务IP和端口号
            changeOrigin: true
            // pathRewrite: {
            //   ['^' + process.env.VUE_APP_BASE_API]: ''
            // }
          }
        },
        // before: require('./mock/mock-server.js')
      },
    

    后端API配置:
    举例:在./src/api目录下创建项目相关的api服务,创建文件project.js,引入项目增删改查接口服务。

    import request from '@/utils/request'
    export function fetchList(query) {
      return request({
        url: '/tmp/pro/get_projects/',
        method: 'get',
        params: query
      })
    }
    export function createProject(data) {
      return request({
        url: '/tmp/pro/create/',
        method: 'post',
        data
      })
    }
    export function updateProject(data) {
      return request({
        url: '/tmp/pro/update/',
        method: 'post',
        data
      })
    }
    export function deleteProject(data) {
      return request({
        url: '/tmp/pro/delete/',
        method: 'post',
        data
      })
    }
    

    前端调用API:

    import {fetchList, createProject, updateProject, deleteProject} from '@/api/project'
        getList() {
          this.listLoading = true
          fetchList(this.listQuery).then(response => {
            this.list = response.data.items.map(row => {
              return {
                ...row,
                edit_status: false,
                unfold_status: false,
                interval: [row.start_time, row.plan_end_time]
              }
            })
            this.listQuery.page = response.data.page
            this.total = response.data.total
            this.listLoading = false
          })
        },
        createData() {
          this.$refs['dataForm'].validate((valid) => {
            if (valid) {
              this.temp.start_time = parseTime(this.temp.interval[0])
              this.temp.plan_end_time = parseTime(this.temp.interval[1])
              createProject(this.temp).then((response) => {
                if (response.code !== 20000) {
                  return Promise.reject(new Error(response.message || 'Error'))
                } else {
                  // this.list.unshift(this.temp)
                  this.dialogFormVisible = false
                  this.$notify({
                    title: 'Success',
                    message: '新增成功!',
                    type: 'success',
                    duration: 2000
                  })
                  this.getList()
                }
              })
            }
          })
        },
    

    部署

    1、Vue工程打包

    1)vue.config.js,修改配置publicPath: './'
    2).env.production,修改配置VUE_APP_BASE_API = '/'
    3)在vue项目根路径下执行 npm run build:prod --report

    2、Django项目的Docker镜像部署

    1)将Django项目包(tmp文件夹)上传到服务器目录/home/下,在/home/tmp/目录下创建front文件夹,再将打包后的vue代码(dist文件夹)上传到front文件夹下;
    2)已有centos7+python3.6.8+django库的基础镜像,使用potainner新建容器,配置如下:


    选择基础镜像和端口映射.png
    配置项目运行命令和工作目录.png
    容器和服务器目录映射

    3)新建容器完成,启动容器即可。

    3、Nginx配置

    1)下载并安装nginx,使用start nginx命令启动服务,测试nginx是否安装成功;
    2)修改nginx.conf配置文件如下:

     server {
        listen 9001; //前端访问端口
        location / {
           root /home/tmp/front/dist;   //放置打包后的vue工程代码
           index index.html index.htm;
           autoindex on;
           autoindex_exact_size on;
           autoindex_localtime on;
        }
       location ^~ /tmp/ {
           proxy_http_version 1.1;
           proxy_set_header Host $http_host;
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-Host $http_host;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header X-Forwarded-Proto $scheme;
           proxy_set_header Upgrade $http_upgrade;
           proxy_set_header Accept-Encoding 'gzip';
           proxy_set_header Connection "upgrade";
           add_header Access-Control-Expose-Headers "token";
           proxy_pass http://127.0.0.1:8081/tmp/;    //Django服务地址
        }
        add_header Access-Control-Allow-Origin "*";
        default_type 'text/html';
        charset utf-8;
     }
    

    3)修改配置后重启nginx服务,重启命令nginx -s reload,访问http://127.0.0.1:9001/。

    项目源码

    Vue前端工程:https://gitee.com/xingxixi/vue-tm.git
    Django后端工程:https://gitee.com/ddlyr/tmp.git
    注:该项目未开源,需要源码的同学请注册码云后,联系我申请开通权限。

    相关文章

      网友评论

          本文标题:Django+Vue+Nginx开发和部署

          本文链接:https://www.haomeiwen.com/subject/nhoqyltx.html