Django+Vue+Nginx开发和部署

概述

开发采用前后端分离方式:
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开发和部署)