技术栈
node.JS, vue.js, axios, python, django, ORM, restful API, djangorestframework, MySQL, nginx, jenkins.
环境配置
操作系统
Windows 7 旗舰版, Service Pack 1.
前端
Node.JS
- >node -v
- v12.18.0
- >NPM -v
- 6.14.4
vue.JS
- >vue -V(大写)
- @vue/cli 4.4.1
后端
- Python
- >python --version
- Python 3.7.2
- Django
- >python -m django --version
- 3.0.7
数据库
- MySQL
- >mysqladmin --version
- mysqladmin Ver 8.0.19 for Win64 on x86_64 (MySQL Community Server - GPL)
命令行登录 MySQL,
- >MySQL -u root -p
- Enter password: ******
查询数据库,
- MySQL> show databases;
- +--------------------+
- | Database |
- +--------------------+
- | information_schema |
- | MySQL |
- | new_schema |
- | performance_schema |
- | sakila |
- | sys |
- | world |
- +--------------------+
- 7 rows in set (0.00 sec)
代理
Nginx
在 nginx 安装目录执行 start nginx, 浏览器访问 http://localhost:80,
持续集成
Jenkins
安装后, 会自动打开 http://localhost:8080/,
软件安装过程就不赘述了, 聪明的你一定知道怎么安.
项目搭建
本文的目的是走通整个项目的链路, 于是会 "弱化" 掉系统功能的实现.
创建后端工程
执行 django-admin startproject djangotest 创建项目.
cd djangotest, 执行 python manage.py startapp myapp 创建应用.
python manage.py runserver, 启动服务, 访问 http://localhost:8000/,
创建 RESTful API
安装 mysqlclient 和 djangorestframework,
- pip --default-timeout=6000 install -i https://pypi.tuna.tsinghua.edu.cn/simple mysqlclient
- pip --default-timeout=6000 install -i https://pypi.tuna.tsinghua.edu.cn/simple djangorestframework
在 settings.py 中, 添加'rest_framework'和'myapp',
- INSTALLED_APPS = [
- 'django.contrib.admin',
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- 'rest_framework',
- 'myapp',
- ]
同时修改数据库配置,
- DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.mysql',
- 'HOST': '127.0.0.1',
- 'PORT': 3306,
- 'NAME': 'world',
- 'USER': 'root',
- 'PASSWORD': '123456'
- }
- }
在 myapp\models.py 添加 model,model 叫做 HellloDjango, 有 2 个字段 id 和 name,
- from django.db import models
- # Create your models here.
- class HelloDjango(models.Model):
- id = models.AutoField(primary_key=True)
- name = models.CharField(null=False, max_length=64, unique=True)
执行 python manage.py makemigrations, 提交,
- >python manage.py makemigrations
- Migrations for 'myapp':
myapp\migrations\0001_initial.py
- Create model HelloDjango
执行 python manage.py migrate, 创建,
- >python manage.py migrate
- Operations to perform:
- Apply all migrations: admin, auth, contenttypes, myapp, sessions
- Running migrations:
- Applying contenttypes.0001_initial... OK
- Applying auth.0001_initial... OK
- Applying admin.0001_initial... OK
- Applying admin.0002_logentry_remove_auto_add... OK
- Applying admin.0003_logentry_add_action_flag_choices... OK
- Applying contenttypes.0002_remove_content_type_name... OK
- Applying auth.0002_alter_permission_name_max_length... OK
- Applying auth.0003_alter_user_email_max_length... OK
- Applying auth.0004_alter_user_username_opts... OK
- Applying auth.0005_alter_user_last_login_null... OK
- Applying auth.0006_require_contenttypes_0002... OK
- Applying auth.0007_alter_validators_add_error_messages... OK
- Applying auth.0008_alter_user_username_max_length... OK
- Applying auth.0009_alter_user_last_name_max_length... OK
- Applying auth.0010_alter_group_name_max_length... OK
- Applying auth.0011_update_proxy_permissions... OK
- Applying myapp.0001_initial... OK
- Applying sessions.0001_initial... OK
看看数据库, 新增了 auth_和 django_开头的表, 以及 model 映射的表 myapp_hellodjango,
- MySQL> show tables;
- +----------------------------+
- | Tables_in_world |
- +----------------------------+
- | auth_group |
- | auth_group_permissions |
- | auth_permission |
- | auth_user |
- | auth_user_groups |
- | auth_user_user_permissions |
- | city |
- | country |
- | countrylanguage |
- | django_admin_log |
- | django_content_type |
- | django_migrations |
- | django_session |
- | myapp_hellodjango |
- +----------------------------+
- 14 rows in set (0.00 sec)
插入 2 条测试数据,
- MySQL> insert into myapp_hellodjango(name) values('hello');
- Query OK, 1 row affected (0.09 sec)
- MySQL> insert into myapp_hellodjango(name) values('django');
- Query OK, 1 row affected (0.20 sec)
- MySQL> select * from myapp_hellodjango;
- +----+--------+
- | id | name |
- +----+--------+
- | 2 | django |
- | 1 | hello |
- +----+--------+
- 2 rows in set (0.00 sec)
照着官网的例子, 在 myapp 目录下新增 urls.py, 添加 REST 代码,
- from django.conf.urls import url, include
- from rest_framework import routers, serializers, viewsets
- from .models import HelloDjango
- # Serializers define the API representation.
- class HelloSerializer(serializers.HyperlinkedModelSerializer):
- class Meta:
- model = HelloDjango
- fields = ['id', 'name']
- # ViewSets define the view behavior.
- class HelloViewSet(viewsets.ModelViewSet):
- queryset = HelloDjango.objects.all()
- serializer_class = HelloSerializer
- # Routers provide an easy way of automatically determining the URL conf.
- router = routers.DefaultRouter()
- router.register(r'hello', HelloViewSet)
- urlpatterns = [
- url(r'demo/', include(router.urls)),
- ]
在 djangotest 下的 urls.py 中添加路由,
- from django.contrib import admin
- from django.urls import path, include
- urlpatterns = [
- path('admin/', admin.site.urls),
- path('api/', include('myapp.urls'))
- ]
通过这 2 个 urls.py 文件的指定, API 接口的路径为,/API/demo/hello.
执行 python manage.py runserver 启动服务, 使用 postman 来调用 http://127.0.0.1:8000/api/demo/hello/. 先发 1 个 post 请求, 往数据库新增 1 条数据,
再发 1 个 get 请求, 会看到返回了 3 条数据, 2 条预先插入的数据, 1 条 post 请求新增的数据,
创建前端工程
在 djangotest 根目录下, 执行 vue create vuetest, 创建 vue 工程.
默认安装, 一路回车, 啪啪啪.
开始创建,
- Vue CLI v4.4.1
- a Creating project in D:\cicd\vuetest.
- a Initializing Git repository...
- aa Installing CLI plugins. This might take a while...
创建成功,
- a Successfully created project vuetest.
- a Get started with the following commands:
- $ cd vuetest
- $ NPM run serve
执行 cd vuetest 和 NPM run serve, 前端工程就启动起来了, 访问 http://localhost:8080/,Welcome to Your Vue.JS App,
前端调后端接口
此时 djangotest 的目录结构为,
├─djangotest
│ ├─djangotest
│ ├─myapp # App
│ ├─vuetest # 前端
│ ├─manage.py
修改 vuetest\src\components\HelloWorld.vue, 添加 {{info}}, 用来展示后端 API 返回的数据,
- <div class="hello">
- {{info}}
- <h1>{{ msg }}</h1>
同时在 < script > 中使用 axios 添加 Ajax 请求, 请求 http://127.0.0.1:8000/api/demo/hello/, 将 response.data 赋值给 info,
- <script>
- export default {
- name: 'HelloWorld',
- props: {
- msg: String
- },
- data() {
- return {
- info: 123
- }
- },
- mounted () {
- this.$axios
- .get('http://127.0.0.1:8000/api/demo/hello/')
- .then(response => (this.info = response.data))
- .catch(function (error) { // 请求失败处理
- console.log(error);
- });
- }
- }
- </script>
为了运行起来, 需要安装 axios,
NPM install --save axios
并在 vuetest\src\main.JS 中引入,
- import Vue from 'vue'
- import App from './App.vue'
- import axios from 'axios'
- Vue.config.productionTip = false
- Vue.prototype.$axios = axios;
- new Vue({
- render: h => h(App)
- }).$mount('#app')
分别启动后端和前端服务,
- python manage.py runserver
- cd vuetest
- NPM run serve
嚯! Ajax 请求失败了, F12 可以看到报错信息,
localhost/:1 Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/demo/hello/' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
django 的端口是 8000,vue 的端口是 8080,vue 在请求 django 的时候, 出现了跨域问题. 浏览器有个同源策略, 域名 + 端口 + 协议都相同才认为是同一来源.
通过配置 django 来解决, 先安装 django-cors-headers,
pip install django-cors-headers
在 settings.py 中添加中间件和开关,
- MIDDLEWARE = [
- 'django.middleware.security.SecurityMiddleware',
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'corsheaders.middleware.CorsMiddleware', # 添加
- 'django.middleware.common.CommonMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
- 'django.middleware.clickjacking.XFrameOptionsMiddleware',
- ]
- CORS_ORIGIN_ALLOW_ALL = True # 添加
此时 vue 就可以请求到 django 提供的接口了, http://localhost:8080/
前后端结合
在 vuetest 目录下创建 vue.config.JS, 这是因为 django 只能识别 static 目录下的静态文件, 这里指定 vue 生成静态文件时套一层 static 目录,
- module.exports = {
- assetsDir: 'static'
- };
在 vuetest 目录下执行 NPM run build, 生成静态文件到 vuetest/dist 文件夹.
修改 urls.py, 指定 django 的模板视图,
- from django.conf.urls import url
- from django.contrib import admin
- from django.urls import path, include
- from django.views.generic import TemplateView
- urlpatterns = [
- path('admin/', admin.site.urls),
- path('api/', include('myapp.urls')),
- url(r'^$', TemplateView.as_view(template_name="index.html")),
- ]
在 settings.py 中配置模板目录为 dist 文件夹,
- TEMPLATES = [
- {
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': ['appfront/dist'],
- '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',
- ],
- },
- },
- ]
指定静态文件目录为 vuetest/dist/static,
- # Add for vuejs
- STATICFILES_DIRS = [
- os.path.join(BASE_DIR, "vuetest/dist/static"),
- ]
浏览器访问 http://localhost:8000/, 显示的不再是 django 的欢迎页面, 而是 vue 的页面.
前后端结合完成. vue 的 8080 可以停了.
Nginx 转发
nginx 常用 3 个命令, 启动, 重新加载, 停止,
- nginx start
- nginx -s reload
- nginx -s stop
修改 \ conf\nginx.conf, 监听端口改为 8090, 添加转发 proxy_pass http://localhost:8000;
- server {
- listen 8090;
- server_name localhost;
- #charset koi8-r;
- #access_log logs/host.access.log main;
- location / {
- root HTML;
- index index.HTML index.htm;
- proxy_pass http://localhost:8000;
- }
执行 nginx start, 浏览器访问 http://localhost:8090/, 也能正常访问 djangotest.
通过 nginx 将 8090 转发到了 8000.
持续集成
本来想弄个 pipline 的, 无奈家里这台破机器安装失败, Windows 也没有 Linux 对 jenkins 支持好, 只能将就做个鸡肋版本.
New Item, 命名为 vuetest, 添加 vue 的 build 脚本,
- d:
- cd D:\cicd\djangotest\vuetest
- NPM run build
New Item, 命名为 djangotest, 添加 django 的 build 脚本,
- d:
- cd D:\cicd\djangotest
- python manage.py runserver
直接执行会报错 python 不是可运行命令. 添加 python 环境变量, 在首页左下角,
把路径 D:\Python37 添加为环境变量 path 并保存,
建好的这 2 个 job 就可以用来编译 vue 和启动 django 了,
专注测试, 坚持原创, 只做精品. 欢迎关注公众号『东方 er』
版权申明: 本文为博主原创文章, 转载请保留原文链接及作者.
来源: https://www.cnblogs.com/df888/p/13191065.html