一, 背景
在工作中我们经常须要构件一些基于 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 路径下载:
https://github.com/rogerlh/django_with_vue.git
来源: https://cloud.tencent.com/developer/article/1005607?fromSource=waitui