天天看點

測試同學動手搭個簡易web開發項目

技術棧

node.js, vue.js, axios, python, django, orm, restful api, djangorestframework, mysql, nginx, jenkins.

目錄

  • 技術棧
  • 環境配置
    • 作業系統
    • 前端
      • Node.js
      • Vue.js
    • 後端
      • Python
      • Django
    • 資料庫
      • MySQL
    • 代理
      • Nginx
    • 持續內建
      • Jenkins
  • 項目搭建
    • 建立後端工程
    • 建立RESTful API
    • 建立前端工程
    • 前端調後端接口
    • 前後端結合
  • Nginx轉發
  • 持續內建

環境配置

作業系統

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,

測試同學動手搭個簡易web開發項目

持續內建

Jenkins

安裝後,會自動打開http://localhost:8080/,

測試同學動手搭個簡易web開發項目

軟體安裝過程就不贅述了,聰明的你一定知道怎麼安。

項目搭建

本文的目的是走通整個項目的鍊路,于是會“弱化”掉系統功能的實作。

建立後端工程

執行

django-admin startproject djangotest

建立項目。

cd djangotest

,執行

python manage.py startapp myapp

建立應用。

python manage.py runserver

,啟動服務,通路http://localhost:8000/,

測試同學動手搭個簡易web開發項目

建立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條資料,

測試同學動手搭個簡易web開發項目

再發1個get請求,會看到傳回了3條資料,2條預先插入的資料,1條post請求新增的資料,

測試同學動手搭個簡易web開發項目

建立前端工程

在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,

測試同學動手搭個簡易web開發項目

前端調後端接口

此時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/

測試同學動手搭個簡易web開發項目

前後端結合

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可以停了。

測試同學動手搭個簡易web開發項目

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腳本,

測試同學動手搭個簡易web開發項目

New Item,命名為djangotest,添加django的build腳本,

測試同學動手搭個簡易web開發項目

直接執行會報錯python不是可運作指令。添加python環境變量,在首頁左下角,

測試同學動手搭個簡易web開發項目

添加環境變量并儲存,

測試同學動手搭個簡易web開發項目

建好的這2個job就可以用來編譯vue和啟動django了,

測試同學動手搭個簡易web開發項目

專注測試,堅持原創,隻做精品。歡迎關注公衆号『東方er』

版權申明:本文為部落客原創文章,轉載請保留原文連結及作者。

繼續閱讀