云服务器Nginx+uwsgi+MySQL部署Django+Vue网上书店项目

768 阅读7分钟

这是我的第一篇技术博客,主要是想要开始纪录和回顾做过的一些事情和踩过的一些坑。把一个东西做出来了并不代表实际真的能够说出来个所以然,所以在某种程度上,我把它当做一种日记和技术成长的结合体,希望可以有一个好的开头。

这个项目的起源是大三上学期末的计算机网络实验,目标是搭建一个基本功能齐全的网上书店。其实之前在自强做前端的工作的时候就一直对后端以及服务器的操作比较好奇,所以这次干脆直接租了个云服务器,自己从0开始一步一步完成整个项目框架的搭建和部署。

本地篇

在把项目部署到服务器之前,首要的目标是让这个搭好的项目框架先在本地正常跑起来。

本地安装MySQL数据库

具体教程见:MySQL的详细安装教程

安装好之后进入MySQL WorkBench,配置一个本地的数据库连接,主机为127.0.0.1,端口默认是3306,我这里改成了3307,下文也会对应3307来写。

进去之后新建一个Schema示例,也就是新建一个数据库,我命名为test

搭建Django项目

首先声明:在尝到JetBrains全家桶的甜头之后,又有谁还用vscode呢,学生认证全家桶免费用不香吗?以及你需要配置好python环境,我是用的Anaconda来管理python环境,具体教程参见:Anaconda配置python环境

新建项目

安装最新版Pycharm,进入Pycharm后左上角新建一个Django项目,我建的项目名称叫做bookstore,注意要使用你的Anaconda去新建一个虚拟环境,与别的python包进行隔离管理。刚刚建好的文件目录应该是这样的:

在项目文件夹下面:

  • manage.py是后续用来进行一系列操作的文件,非常重要,功能类似于引擎
  • templates文件夹用来存放一些前端的html文件,如果只用Django做后端的话,这个文件夹其实不用管
  • 最外层的bookstore是你的项目文件夹,再下一级的bookstore文件夹是你的项目配置文件夹,里面存放着项目的一些配置文件如settings, wsgi等等。注意区分项目、应用两个名词

在项目配置文件夹下面,我们需要用到的文件有:

  • settings.py是对项目配置进行设置的文件
  • urls.py是Django中管理路由的文件,后端写的接口需要放进去前端才能请求到
  • wsgi.py是后续部署到服务器上会用到的文件,本地部署暂时先可以不管

接着在项目文件夹下用命令python manage.py startapp 目标应用名称,比如我创建的应用叫做api,那么就是python manage.py startapp api。创建完成之后项目文件夹下面会多出来一个应用文件夹叫做api。

然后把创建的应用加进settings.py中。在settings.py中找到INSTALLED_APPS属性,在最后添加上应用名称就好啦。

接着还要设置一下ALLOW HOST让所有IP都能访问:

连接MySQL数据库

不知道有没有小伙伴发现项目文件夹下面还有个dp.sqlite3文件(有的可能没有),这是因为Django创建项目默认用的是sqlite3数据库,现在我们要把他换成MySQL。

依然是进入settings.py中修改相应的配置。找到DATABASES属性,将里面的内容修改为

'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'test',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': '127.0.0.1',
        'PORT': '3307'
    }

其中每个字段要换成你在建数据库的时候设置的对应的属性,比如我之前新建的数据库名字叫test,用户名和密码是root和123456,主机地址是127.0.0.1,端口号是3307

接着需要安装一个叫做pymysql的包 pip install pymysql

然后修改项目配置文件夹下面的__init__.py:

import pymysql
pymysql.version_info = (1, 4, 0, 'final', 0)
pymysql.install_as_MySQLdb()

在建好之后使用命令python manage.py migrate进行数据迁移,如果流程正确,迁移的时候会显示各个文件迁移的进度,不过闪的很快。迁移成功后可以在MySQL WorkBench上查看test数据库里面,是不是多了好几个表嘞。这些存储的就是Django自带的一些用户的操作日志记录啊什么的。这样我们就算成功连接到本地数据库了。

建表

如果我要写一个会员登录的接口,那么可以抽象出来一个简单的会员类,他的属性有account(账号),password(密码),name(姓名),其中account是键。

进入我们的应用文件夹api,可以看到有个models.py文件,这个文件就是我们构建不同的抽象类的地方。

from django.db import models

# Create your models here.

class Member(models.Model):
    account = models.CharField(max_length=64, primary_key=True)
    password = models.CharField(max_length=64)
    name = models.CharField(max_length=64)

这样我们就构建出来了一个Member类。Django会自动把这个类在数据库中建一个表,并不需要我们手动去输入SQL语句。使用命令python manage.py makemigrations表明我们更新了数据库的内容,接着使用python manage.py migrate来一次大迁徙。完成后到数据库中看看,是不是多了个api_member的表?

写接口

我们先偷偷往数据库的api_member表中添加两条数据作为我们的元老级会员。

接着在应用文件夹api下的views.py写我们的接口,我的函数名叫做login

from django.http import HttpResponse,JsonResponse //引入http响应方法
from api.models import * //把我们写好的类引进来


def login(request):
    print(request)
    if request.method == 'POST':
        account = request.POST.get('account') //从前端传来的表单中获取account字段的值
        password = request.POST.get('password')
        print(account, password)
        if Member.objects.filter(account=account).exists(): //在数据库中检查是否存在account,其中filter是选择操作
            user = Member.objects.get(account=account)
            if user.password != password:
                return HttpResponse('wrong')
            else:
                return HttpResponse('right')
        else:
            return HttpResponse('not exist')

项目文件夹下的urls.py中,改成下面的内容:

from django.contrib import admin
from django.urls import path,include
from api import views as api_views //把应用文件夹下的views函数导进来


urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', api_views.login), //定义接口路径名为login/
]

这样我们的一个login/的接口就写好啦,用命令python manage.py runserver把项目在本地跑起来,可以用postman测试一下我们的接口http://127.0.0.1:8000/login/,但还不能得意,因为Vue的项目跑起来的时候端口号大概率是8080跟Django的不一样,涉及到跨域会禁止访问,所以还要配置cors以便于处理跨域

处理跨域

具体参见: 使用django-cors-header处理跨域

搭建Vue项目

新建项目

使用WebStorm新建项目(对没错,又是JetBrains)

搭建页面

使用接口

首先把vuex中的初始url设置为正在跑着的http://127.0.0.1/,再写请求

this.$axios.post(this.$store.state.url + 'login/', data).then(res => {
        console.log(res);
        if(res.data === 'right'){
          this.$message.success('登录成功!');
          this.$router.push({path: '/home'})
          this.$store.commit('setIdentity', '管理员');
        } else if(res.data === 'wrong') {
          this.$message.error('密码错误!')
        } else {
          this.$message.error('此账号不存在!')
        }

      })
    }

至此本地的登录就完成啦。

服务器篇

首先购买云服务器。听闻腾讯云的轻量级服务器对学生有优惠,果断买之。

经过一系列学生认证和支付操作就可以拿到27元三个月的轻量级服务器了,用来搭环境练练手什么的,超值有没有!

接着我们进入腾讯云的控制台,在轻量级服务器的页面下可以看到我们刚刚购买的服务器。

选CentOS作为操作系统也是因为他相当出名吧,也是宿舍长的指导?

给服务器配好密码后,这个服务器就算真正是落到我们手里任我们摆布啦。先在防火墙中开启8000-8001,和8080-8081端口,听我的,开就完事了(doge)

接着我们需要在本地下载两个软件: XShell和Xftp,安装好后打开XShell和我们的云服务器进行连接,连接成功后,XShell就是我们的远程桌面了,以后配置服务器的所有操作在里面进行。在XShell建立连接后可以在XShell里打开Xftp,就可以可视化操作我们服务器上的文件了。

下一步就是配置我们Django项目的运行环境了。CentOS自带的是python2.x的环境,我们要更新至3.x的版本,有很多种方法。可以参照:CentOS安装python3环境

接着我们安装mysql,可以参考: CentOS安装MySQL

接着安装uwsgi和nginx:

  • pip install uwsgi
  • yum install nginx

有同学可能会发现yum报错了,这是因为系统yum支持原来的python2.x环境,现在被更新到3.x了所以不行。解决办法参考:yum报错

接下来是无数的血和泪:配置uwsgi和nginx的配置文件

配置uwsgi

首先我们把本地的Django项目文件夹用Xftp传到服务器上。我的项目文件夹在服务器中的位置是/djangoTest/bookstoreDjango。进入项目文件夹下新建一个名字叫uwsgi的文件夹(用来存放uwsgi的启动初始化文件等等),uwsgi文件夹应该跟manage.py是同级的。接着进入uwsgi文件夹,新建一个文件uwsgi.ini,里面放进如下内容:

[uwsgi]
#http = :8000
socket = 127.0.0.1:8000 
# 自身项目文件夹在服务器上地址
chdir = /djangoTest/bookstoreDjango/ 

#自身项目中的wsgi
module = bookstoreDjango.wsgi 
master = true 
processes = 1 
threads = 2  # 线程数
max-requests = 2000 # 最大请求
chmod-socket = 664
vacuum = true 
# uwsgi文件存放地址
stats = %(chdir)/uwsgi/uwsgi.status
pidfile = %(chdir)/uwsgi/uwsgi.pid 
daemonize = %(chdir)/uwsgi/uwsgi.log

这里要注意几个点:

  • http属性是当只使用uwsgi作为服务器时要用到的,我们在这里不用
  • socket属性是后面要跟nginx对接的,这个值务必设置成内网地址比如127.0.0.1:8000,不要设置成服务器的公网ip了!!!都是血和泪啊...
  • module属性是bookstoreDjango.wsgi的意思是进入到下一级的bookstoreDjango文件夹,指向其中的wsgi.py文件

之后我们就可以在uwsgi文件夹下使用uwsgi --ini uwsgi.ini启动uwsgi的服务了。我猜你会因为第一次接触而启动了不知道多少次,这样后台就会有很多个uwsgi进程。

怎么停止uwsgi的服务呢?

首先可以用ps aux|grep uwsgi查看与uwsgi相关的正在运行的进程。如果有一个以上的条目信息就说明uwsgi正在运行,可以使用uwsgi --stop uwsgi.pid来停止服务,也可以pkill -f uwsgi -9强制杀掉进程。

注意在每次修改完uwsgi.ini之后都要重启uwsgi服务。

配置nginx

通过nginx -t可以查看到nginx的配置文件是在这:/etc/nginx/nginx.conf

编辑这个文件,找到里面的server字段修改成下面的内容:

server {
    listen 80;
    server_name 119.29.24.77;
    charset utf-8;

    location / {
      # 监听端口和uwsgi相同
      uwsgi_pass 127.0.0.1:8000;
      include /etc/nginx/uwsgi_params;
    }

    location /static {
      #uwsgi配置的静态链接的地址
      alias /djangoTest/collected_static/; 
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

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

其中要注意的几个点:

  • listen是要监听的端口号,80是默认端口,后续在Vue项目中需要把url改成80端口
  • server_name修改成公网ip
  • location下的uwsgi_pass属性要改成前面配置uwsgi.ini中socket属性一样的值,这里是127.0.0.1:8000

如何启动nginx呢?

  • systemctl start nginx启动
  • systemctl stop nginx停止
  • systemctl restart nginx重启

更改Django中的数据配置

使用MySQL WorkBench新建一个主机为服务器公网ip的数据库连接,配置好后进去新建一个数据库。把django项目配置文件夹中settings里面的数据库参数更改为刚刚建好的数据库对应的参数,再python manage.py migrate进行数据迁移。

部署Vue项目

进入config文件夹下面的index.js,在build那部分(不是dev)找到如下字段并且更改:

// Paths
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: './',

修改了 assetsPublicPath的值为'./'

进入build文件夹下面的utils.js,找到如下字段并且更改:

return ExtractTextPlugin.extract({
        use: loaders,
        fallback: 'vue-style-loader',
        publicPath: '../../'
      })

这里实际上是加了一行publicPath,目的是为了部署到服务器端后,静态资源也能正常访问。如果没有这个且使用了element-ui的东西,会出现图标丢失。

最后npm run build打包Vue项目,成功后项目文件夹下会多出一个dist文件夹。我们把dist上传到服务器上。

找到nginx的配置文件nginx.conf,再次修改,添加一个server如下:

server {
              listen 8080;     #1.你想让你的这个项目跑在哪个端口
              server_name 119.29.24.77;     #2.当前服务器ip
       
       
	location / {
           root   /bookstore_frontend/dist/;     #3.dist文件的位置
            try_files $uri $uri/ /index.html;     #4.重定向,内部文件的指向(照写)
       }

       }

其中listen注意不要再填80端口了,因为会跟之前设置的撞车。location下的root属性填你上传的dist文件夹在服务器的位置。

至此,所有配置都配置完毕,接下来就是把uwsgi和nginx启动起来,看看我们的成果啦。因为Vue是部署在8080端口的,所以我们在浏览器地址栏输入服务器公网ip + :8080就可以访问到Vue搭建的页面啦。

功能测试成功,所有人都可以访问到这个ip地址了,不知道你成功了没有呢?

ps:写在最后的话

因为自己在配置服务器的时候踩了很多坑,很多时候甚至烦躁不堪,所以想写一篇全面一点的全栈搭建框架流程帮助看到这篇博客的人。其中可能不乏一些遗漏的地方,希望大家可以在评论区指出来,我也会进一步完善。现在是2020.12.25的晚上20:00,第一篇博客送给自己当做圣诞礼物吧hhh,写这个可比写论文有意思多了。