一、 背景
在工作中我們經常須要構件一些基于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路徑下載下傳: