让我们创建一个Django + Vue.js的开发环境
你想做什么?
本文档介绍了一种稍微不同的方法,使用Vue.js作为前端开发框架创建了一个单页面应用程序,并使用Django和Django REST框架作为后端,提供了Web API。虽然已经有一些先驱者使用了类似的解决方案,但我们试图尝试一种不同的方法,故特此撰写此文。
-
- Django + Webpack を使ってVueを動かす
- Django REST framework with Vue.js
怎么做?
在Django项目中,通常会将html文件解释为模板并进行渲染,但是该模板语法与Vue非常相似。因此,带有Vue模板语法的html无法与Django模板共存。
因此,通过使用webpack将前端拆分为Vue的单文件组件,并编写代码来避免这个问题。由于Django模板和Vue在渲染时的时机不同,即在服务器端和客户端端分别进行渲染,因此通过将Vue部分作为组件从html文件中分离出来,可以使两者共存。也许还有更聪明的方法!
安装环境
使用Vue.js的Vuetify框架来实现前端,轻松地实现类似于Material Design的效果。只需使用vue-cli,就能快速设置一个使用webpack的前端项目。真方便!请先安装npm。项目名称随意,这里我们将其命名为miniblog。
% npm i -g vue-cli
% vue init vuetifyjs/webpack miniblog
如果没有特殊要求,你可以直接按Enter键,无需更改任何设置。完成后,立即使用npm run dev命令启动webpack开发服务器,并打开http://localhost:8080/,你应该能看到示例显示出来。
首先,我们创建一个Django项目。首先,在virtualenv中创建一个Python3的虚拟环境并安装Django。由于Django2.0不支持Python2,所以如果使用Python2,请使用较旧的版本。请预先安装好virtualenv。虚拟环境的名称可以随意取,这里我们使用venv。
% cd miniblog/
% virtualenv -p /path/to/python3 venv
% . venv/bin/activate
(venv) % pip install django djangorestframework
创建一个Django项目,并将miniblog目录直接作为项目根目录。顺便添加一个名为entry的Django应用程序。
(venv) % django-admin startproject miniblog .
(venv) % django-admin startapp entry
完成后,在终端输入python manage.py runserver以启动Django开发服务器,在浏览器中打开http://localhost:8000/,应该会显示启动页。现在一切所需已准备就绪。
改變環境
我們將調整webpack的設定,將生成的靜態資源放置在Django指定的目錄中。我們將編輯config/index.js檔案。
...
module.exports = {
dev: {
...
proxyTable: {
'/api' : {
target: 'http://localhost:8000',
changeOrigin: true,
pathRewrite: { // 開発サーバーでもDjangoのAPIにアクセスできるように設定
'^/api': 'api'
}
}
},
...
// デフォルトのSourceMapは相対パスを参照しているらしく、この環境ではバグになる。
cssSourceMap: false,
},
build: { // コンパイルされたファイルをDjangoの所定位置へ
// Template for index.html
index: path.resolve(__dirname, '../templates/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../static'),
assetsSubDirectory: 'build',
assetsPublicPath: '/static/',
...
}
}
环境本身已经完成,接下来需要一些Django的配置,我们将通过测试来完成。
创建一个API
我将创建一个简单的博客API。顺便说一下,我还会完成由webpack生成的单页面应用的路由功能。首先,我需要在配置中添加一些内容。
INSTALLED_APPS = [
~
# 追記
'rest_framework',
'entry',
]
~
TEMPLATES = [
{
'DIRS': [ # webpackはindex.htmlをtemplatesディレクトリに生成する
os.path.join(BASE_DIR, 'templates'),
],
},
]
~
# webpackは先の設定でstaticディレクトリにcssとjsファイルを生成する
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
接下来,我会写出模型。
class Entry(models.Model):
title = models.CharField(max_length=200)
contnt = models.TextField()
date = models.DateField()
接下来,在entry/中添加serializers.py文件,并按照下面的方式进行编辑。
from rest_framework import serializers
from .models import Entry
class EntrySerializer(serializers.ModelSerializer):
class Meta:
model = Entry
fields = (
'id',
'title',
'content',
'date'
)
此外,在views.py文件中,还需要添加以下内容。
from rest_framework import generics
from rest_framework.permissions import AllowAny
from .models import Entry
from .serializers import EntrySerializer
class EntryListAPIView(generics.ListAPIView):
permission_classes = (AllowAny,)
serializer_class = EntrySerializer
queryset = Entry.objects.all()
将以下类似的urls.py文件添加到entry/目录中。
from django.urls import path
from .views import EntryListAPIView
urlpatterns = [
path('entries/', EntryListAPIView.as_view()),
]
请在entry/admin.py文件中添加以下内容。
from django.contrib import admin
from .models import Entry
admin.site.register(Entry)
再写一点!在miniblog/urls.py中添加。
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from .views import index
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('entry.urls')), # APIへのルーティング
path('', index, name='index'), # vueシングルページアプリへのルーティング
] + static(settings.STATIC_URL) # staticディレクトリにルーティング
我要在miniblog/views.py中最后加上一行代码。
from django.shortcuts import render
# webpackが生成したhtmlをそのままテンプレートとして読み込ませる
def index(request):
return render(request, 'index.html', {})
终于完成了!在确认之前,不要忘记进行Entry模型的迁移。
(venv) % python manage.py makemigrations
(venv) % python manage.py migrate
通过这样配置后,我们已经基本上实现了一个类似于API的功能。您可以通过在命令行中使用 “python manage.py createsuperuser” 命令添加管理员用户,然后使用 “python manage.py runserver” 命令启动开发服务器,并访问管理员页面来添加一些条目。之后,当您访问”http://127.0.0.1:8000/api/entries/”时,应该会返回一份以JSON格式呈现的Entry模型列表。有很多地方可以进行修改呢。
其实最好还是写一些CRUD和测试之类的,但这不是我们的重点,就算到这儿吧。
这样,Django的配置就完成了。
尝试使用Vue.js读取API数据。
终于到Vue了。使用axios来处理API的请求。快速安装。
% npm i --save axios
完成后,我们来编写Vue的代码。由于应该已经有了Vuetify的演示代码,我们将对其进行编辑。
<template>
<v-container fluid grid-list-md>
<v-slide-y-transition mode="out-in">
<v-layout row wrap align-center>
<v-flex v-for="entry in entryList">
<v-card>
<v-card-title>
<span class="headline">{{ entry.title }}</span>
</v-card-title>
<v-card-text>
<blockquote>
{{ entry.content }}
<footer>
<small>
<em>—{{ entry.date }}</em>
</small>
</footer>
</blockquote>
</v-card-text>
</v-card>
</v-flex>
</v-layout>
</v-slide-y-transition>
</v-container>
</template>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<script>
import axios from 'axios'
export default {
data () {
return {
entryList: []
}
},
mounted: function () {
console.log('mounted')
// APIを叩く。
// 開発サーバで動作中はちゃんとDjangoの8000番ポートを叩いてくれます。
axios.get('/api/entries/')
.then((response) => {
this.entryList = response.data
})
.catch((error) => {
console.log(error)
})
}
}
</script>
成功了!在执行npm run build之后,再使用django manage.py runserver命令启动开发服务器,然后在http://127.0.0.1:8000/上应该会显示以Entry模型形式排列的内容。API工作正常!
这个环境的优点
我个人认为这个开发环境最棒的地方是可以同时启动Django开发服务器和webpack开发服务器,从而在前端和后端开发中都能享受热重载的好处。只需编写代码,就能立即反映在页面上,无需重新加载浏览器!此外,虽然Django模板也可以共存,但如果使用Vue创建单页应用,老实说Django模板就没有什么优势了。
总结
Django和Vue.js的开发环境已经准备好了。只是在webpack的配置中稍作修改,并没有进行太过任性的设置,所以扩展也应该很容易。不过项目有点杂乱可能是个小问题。再努力一点的话,似乎可以整理好了。
总之,现在可以尽情地在Django和Vue.js上玩了!
我已经在GitHub上准备了一个可以实际运行的项目,这里是链接。