一、 背景
在工作中我們經常須要構件一些基於web的項目,例如內部測試平台、運維系統等。本篇主要介紹如何使用后端Django + 前端Vue.js的技術棧快速地搭建起一套web項目的框架。
為什么使用Django和Vue.js?
Django是Python體系下最成熟的web框架之一,由於Python語言的易用性和受眾面廣,Django框架也因其能夠快速開發網站應用的特性成為了中小型網站開發框架首選。且Django具備的數據分析( Pandas )、任務隊列( Celery )、Restful API( Django REST framework )、ORM(類似java的hibernate)等一眾功能都使得用戶在面對任何建站需求時都能夠得心應手。
Vue.js是當下很火的一個JavaScript MVVM庫,它是以數據驅動和組件化的思想構建的。相比於Angular.js,Vue.js同樣支持雙向綁定、mustache標簽語法等特性,並提供了更加簡潔、更易於理解的API,使得我們能夠快速地上手並使用Vue.js。
本篇使用Vue.js作為前端框架,代替Django本身較為孱弱的模板引擎,Django則作為服務端提供api接口,使得前后端實現完全分離,更適合單頁應用的開發構建。
二、 環境准備
安裝環境:
Django系:
Python 2.7 +
Django 1.11
Mysql 5.7
Python的MySQLdb模塊等
推薦python相關的模塊(包括Django)都使用python自帶的pip安裝器安裝。命令:pip install django即可安裝最新版本的django
Vue.js系:
Node.js 6.1
有關Vue的模塊(包括vue)我們都使用node自帶的npm包管理器安裝
三、 構建Django項目
我們首先使用Django來搭建web后端api框架。
1、 先在終端敲入命令:
django-admin startproject myproject
目錄結構:

2、 進入項目根目錄,創建一個app:
python manage.py startapp myapp
目錄結構:

3、 在myproject下的settings.py配置文件中,把默認的sqllite3數據庫換成我們的mysql數據庫:
# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'myproject', 'USER': 'root', 'PASSWORD': 'root', 'HOST': '127.0.0.1', } }
並把app加入到installed_apps列表里:
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'myapp', ]
4、 在app目錄下的models.py里我們簡單寫一個model如下:
# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models # Create your models here. class Book(models.Model): book_name = models.CharField(max_length=64) add_time = models.DateTimeField(auto_now_add=True) def __unicode__(self): return self.book_name
只有兩個字段,書名book_name和添加時間add_time。如果沒有指定主鍵的話django會自動新增一個自增id作為主鍵
5、 在app目錄下的views里我們新增兩個接口,一個是show_books返回所有的書籍列表(通過JsonResponse返回能被前端識別的json格式數據),二是add_book接受一個get請求,往數據庫里添加一條book數據:
# Create your views here.
@require_http_methods(["GET"]) def add_book(request): response = {} try: book = Book(book_name=request.GET.get('book_name')) book.save() response['msg'] = 'success' response['error_num'] = 0 except Exception,e: response['msg'] = str(e) response['error_num'] = 1 return JsonResponse(response) @require_http_methods(["GET"]) def show_books(request): response = {} try: books = Book.objects.filter() response['list'] = json.loads(serializers.serialize("json", books)) response['msg'] = 'success' response['error_num'] = 0 except Exception,e: response['msg'] = str(e) response['error_num'] = 1 return JsonResponse(response)
可以看出,在ORM的幫忙下,我們的接口實際上不需要自己去組織SQL代碼
6、 在app目錄下,新增一個urls.py文件,把我們新增的兩個接口添加到路由里:
from django.conf.urls import url, include import views
urlpatterns = [ url(r'add_book$', views.add_book, ), url(r'show_books$', views.show_books, ), ]
- 我們還要把app下的urls添加到project下的urls中,才能完成路由:
from django.conf.urls import url, include from django.contrib import admin from django.views.generic import TemplateView import myapp.urls urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api/', include(myapp.urls)), url(r'^$', TemplateView.as_view(template_name="index.html")), ]
- 在項目的根目錄,輸入命令:
python manage.py makemigrations myapp
python manage.py migrate
查詢數據庫,看到book表已經自動創建了:

- 在項目的根目錄,輸入命令:
python manage.py runserver
啟動服務,通過postman測試一下我們剛才寫的兩個接口:
add_book

show_books

四、 構建Vue.js前端項目
1、 先用npm安裝vue-cli腳手架工具(vue-cli是官方腳手架工具,能迅速幫你搭建起vue項目的框架):
`npm install -g vue-cli`
安裝好后,在project項目根目錄下,新建一個前端工程目錄:
vue-init webpack appfront //安裝中把vue-router選上,我們須要它來做前端路由
進入appfront目錄,運行命令:
npm install //安裝vue所須要的node依賴
現在我們可以看到整個文件目錄結構是這樣的:

2、 在目錄src下包含入口文件main.js,入口組件App.vue等。后綴為vue的文件是Vue.js框架定義的單文件組件,其中標簽中的內容可以理解為是類html的頁面結構內容,標簽中的是js的方法、數據方面的內容,而則是css樣式方面的內容:

3、 我們在src/component文件夾下新建一個名為Library.vue的組件,通過調用之前在Django上寫好的api,實現添加書籍和展示書籍信息的功能。在樣式組件上我們使用了餓了么團隊推出的element-ui,這是一套專門匹配Vue.js框架的功能樣式組件。由於組件的 編碼涉及到了很多js、html、css的知識,並不是本文的重點,因此在此只貼出部分代碼:

4、 在src/router目錄的index.js中,我們把新建的Home組件,配置到vue-router路由中:

5、 如果發現列表抓取不到數據,可能是出現了跨域問題,打開瀏覽器console確認:

這時候我們須要在Django層注入header,用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
注意中間件的添加順序
6、 在前端工程目錄下,輸入npm run dev
啟動node自帶的服務器,瀏覽器會自動打開, 我們能看到頁面:

嘗試新增書籍,新增的書籍信息會實時反映到頁面的列表中,這得益於Vue.js的數據雙向綁定特性。
- 在前端工程目錄下,輸入
npm run build
,如果項目沒有錯誤的話,就能夠看到所有的組件、css、圖片等都被webpack自動打包到dist目錄下了:

五、 整合Django和Vue.js
目前我們已經分別完成了Django后端和Vue.js前端工程的創建和編寫,但實際上它們是運行在各自的服務器上,和我們的要求是不一致的。因此我們須要把Django的TemplateView指向我們剛才生成的前端dist文件即可。
1、 找到project目錄的urls.py,使用通用視圖創建最簡單的模板控制器,訪問 『/』時直接返回 index.html:
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api/', include(myapp.urls)), url(r'^$', TemplateView.as_view(template_name="index.html")), ]
2、 上一步使用了Django的模板系統,所以需要配置一下模板使Django知道從哪里找到index.html。在project目錄的settings.py下:
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', ], }, }, ]
3、 我們還需要配置一下靜態文件的搜索路徑。同樣是project目錄的settings.py下:
# Add for vuejs
STATICFILES_DIRS = [ os.path.join(BASE_DIR, "appfront/dist/static"), ]
4、 配置完成,我們在project目錄下輸入命令python manage.py runserver
,就能夠看到我們的前端頁面在瀏覽器上展現:

注意服務的端口已經是Django服務的8000而不是node服務的8080了
六、 部署
由於python的跨平台特性,因此理論上只要在服務器上安裝好所有的依賴,直接把項目目錄拷貝到服務器上即可運行。這里只提一點:如果為項目配置了nginx作為反向代理,那么要在nginx中配置所有的靜態文件path都指向Django項目中配置的靜態文件url,在settings.py中可配置url路徑:
# Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.11/howto/static-files/ STATIC_URL = '/static/'
七、 其他
實例項目的原碼都可以在該git路徑下載: