<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          手把手Django+Vue前后端分離入門教程

          共 8393字,需瀏覽 17分鐘

           ·

          2021-06-04 02:19

          1.前言


          眾所周知,Django對(duì)于網(wǎng)站快速開發(fā)非常友好,這得益于框架為我們做了很多事情,讓我們只需要做一些簡(jiǎn)單的配置和邏輯即可把網(wǎng)站的功能開發(fā)出來(lái)。

          但是,在使用Django的過(guò)程中,有一個(gè)地方一直是比較難受的,那就是使用Django自帶的模版,這種通常需要自己利用HTML+CSS+Jquery的方式總感覺是上一個(gè)時(shí)代的做法,前后端分離無(wú)論對(duì)于開發(fā)效率、多端支持等等都是很有好處的。

          所以,本文希望通過(guò)一個(gè)簡(jiǎn)單的demo,講一講基于Django+Vue的前后端分離開發(fā),將Django作為一個(gè)純后端的服務(wù),為前端Vue頁(yè)面提供數(shù)據(jù)支持。

          本文采用的django版本號(hào)2.2.5,Vue版本2.9.6。

          如果看不完可以先收藏關(guān)注哈~

          開始之前,你要確保Python和pip已經(jīng)成功安裝在電腦上,如果沒有,可以訪問(wèn)這篇文章:超詳細(xì)Python安裝指南?進(jìn)行安裝。

          (可選1)?如果你用Python的目的是數(shù)據(jù)分析,可以直接安裝Anaconda:Python數(shù)據(jù)分析與挖掘好幫手—Anaconda,它內(nèi)置了Python和pip.

          (可選2)?此外,推薦大家用VSCode編輯器,它有許多的優(yōu)點(diǎn):Python 編程的最好搭檔—VSCode 詳細(xì)指南

          請(qǐng)選擇以下任一種方式輸入命令安裝依賴
          1. Windows 環(huán)境 打開 Cmd (開始-運(yùn)行-CMD)。
          2. MacOS 環(huán)境 打開 Terminal (command+空格輸入Terminal)。
          3. 如果你用的是 VSCode編輯器 或 Pycharm,可以直接使用界面下方的Terminal.

          pip install?django

          vue的安裝可見:
          https://www.runoob.com/vue2/vue-install.html

          創(chuàng)建前后端項(xiàng)目:創(chuàng)建一個(gè)文件夾,然后命令行創(chuàng)建項(xiàng)目即可,如下圖:

          932a09026ecf9ac16a8f820217eed936.webp

          命令行進(jìn)入后端文件夾 book_demo,輸入下面命令,瀏覽器登陸 127.0.0.1:8000 看見歡迎頁(yè)即成功。

          python manage.py runserver

          再進(jìn)入前端文件夾 appfront ,輸入下面命令,瀏覽器登陸 127.0.0.1:8080 看見歡迎頁(yè)即成功。

          npm run dev

          上面兩個(gè)命令也是對(duì)應(yīng)前后端項(xiàng)目的啟動(dòng)命令,后面就直接將過(guò)程說(shuō)成啟動(dòng)前/后端項(xiàng)目。

          2.后端實(shí)現(xiàn)


          為了方便后端的實(shí)現(xiàn),作為django做后端api服務(wù)的一種常用插件,django-rest-framework(DRF)提供了許多好用的特性,所以本文demo中也應(yīng)用一下,命令行輸入命令安裝:

          pip install django-rest-framework

          進(jìn)入book_demo目錄,創(chuàng)建一個(gè)新的名為books的應(yīng)用,并在新應(yīng)用中添加urls.py文件,方便后面的路由配置,命令行輸入:

          python manage.py startapp books
          cd?books
          touch urls.py

          現(xiàn)在的目錄結(jié)構(gòu)如下:

          fd968648ff56a52998e24cf92f566b00.webp

          下面開始做一些簡(jiǎn)單的配置:

          將DRF和books配置到django項(xiàng)目中,打開項(xiàng)目中的?settings.py?文件,添加:

          # book_demo/settings.py
          INSTALLED_APPS = [
          ????'django.contrib.admin',
          ????'django.contrib.auth',
          ????'django.contrib.contenttypes',
          ????'django.contrib.sessions',
          ????'django.contrib.messages',
          ????'django.contrib.staticfiles',

          ????# demo add
          ????'rest_framework',
          ????'books',
          ]

          對(duì)整個(gè)項(xiàng)目的路由進(jìn)行配置,讓訪問(wèn) api/ 路徑時(shí)候轉(zhuǎn)到books應(yīng)用中的urls.py文件配置進(jìn)行處理。

          # book_demo/settings.py
          from?django.contrib import?admin
          from?django.urls import?path, include

          urlpatterns = [
          ????path('admin/', admin.site.urls),
          ????path('api/', include('books.urls')), # demo add
          ]

          下面在books應(yīng)用中寫簡(jiǎn)單的邏輯,demo只最簡(jiǎn)單涉及對(duì)書本的增刪改查。因?yàn)檫@一部分不是本文重點(diǎn),所以這里只介紹寫代碼流程和貼代碼,對(duì)代碼不做詳細(xì)解釋:

          在models.py文件中寫簡(jiǎn)單數(shù)據(jù)類Books:

          # books/models.py
          from?django.db import?models


          class?Books(models.Model):
          ????name = models.CharField(max_length=30)
          ????author = models.CharField(max_length=30, blank=True, null=True)

          在books文件夾中創(chuàng)建serializer.py文件,并寫對(duì)應(yīng)序列化器BooksSerializer:

          # books/serializer.py
          from?rest_framework import?serializers

          from?books.models import?Books


          class?BooksSerializer(serializers.ModelSerializer):
          ????class?Meta:
          ????????model = Books
          ????????fields = '__all__'

          在views.py文件中寫對(duì)應(yīng)的視圖集BooksViewSet來(lái)處理請(qǐng)求:

          # books/views.py
          from?rest_framework import?viewsets

          from?books.models import?Books
          from?books.serializer import?BooksSerializer


          class?BooksViewSet(viewsets.ModelViewSet):
          ????queryset = Books.objects.all()
          ????serializer_class = BooksSerializer

          在urls.py文件中寫對(duì)應(yīng)的路由映射:

          # books/urls.py
          from?django.urls import?path, include
          from?rest_framework.routers import?DefaultRouter

          from?books import?views


          router = DefaultRouter()
          router.register('books', views.BooksViewSet)

          urlpatterns = [
          ????path('', include(router.urls)),
          ]

          對(duì)于books應(yīng)用中的內(nèi)容,如果對(duì)DRF和Django流程熟悉的同學(xué)肯定知道都干了些什么,篇幅關(guān)系這里只能簡(jiǎn)單解釋,DRF通過(guò)視圖集ViewSet的方式讓我們對(duì)某一個(gè)數(shù)據(jù)類Model可以進(jìn)行增刪改查,而且不同的操作對(duì)應(yīng)于不同的請(qǐng)求方式,比如查看所有books用get方法,添加一本book用post方法等,讓整個(gè)后端服務(wù)是restful的。

          如果實(shí)在看不懂代碼含義,只需知道這樣做之后就可以通過(guò)不同的網(wǎng)絡(luò)請(qǐng)求對(duì)后端數(shù)據(jù)庫(kù)的Books數(shù)據(jù)進(jìn)行操作即可,后續(xù)可以結(jié)合Django和DRF官方文檔對(duì)代碼進(jìn)行學(xué)習(xí),或關(guān)注本人未來(lái)分享的內(nèi)容。

          到這里,可以運(yùn)行一下后端項(xiàng)目看看效果,命令行運(yùn)行:

          python manage.py makemigrations
          python manage.py migrate
          python manage.py runserver

          得益于DRF提供的api可視化界面,瀏覽器訪問(wèn)?127.0.0.1:8000/api/books/?,如果出現(xiàn)了以下界面并添加數(shù)據(jù)正常,則說(shuō)明后端的基本邏輯已經(jīng)ok了~下圖為添加了一條數(shù)據(jù)之后的效果。

          b0b3d3d67cfabb48ece9e5063125165b.webp

          3.前端實(shí)現(xiàn)


          接下來(lái)的工作以appfront項(xiàng)目目錄為根目錄進(jìn)行,開始寫一點(diǎn)前端的展示和表單,希望達(dá)到兩個(gè)目標(biāo),一是能從后端請(qǐng)求到所有的books列表,二是能往后端添加一條book數(shù)據(jù)。說(shuō)白了就是希望把上面的頁(yè)面用Vue簡(jiǎn)單實(shí)現(xiàn)一下,然后能達(dá)到相同的功能。

          對(duì)于Vue項(xiàng)目中各個(gè)文件的功能這里也不多解釋,可以參考其文檔系統(tǒng)學(xué)習(xí)。這里只需要知道歡迎頁(yè)面中的樣式是寫在App.vue和components/HelloWorld.vue中即可。

          這里直接用HelloWorld.vue進(jìn)行修改,只求功能不追求頁(yè)面了~


          上滑查看更多代碼

          // appfront/src/components/HelloWorld.vue
          <template>
          ??<div?class="hello">
          ????<h1>{{ msg }}</h1>
          ????<!-- show books list -->
          ????<ul>
          ??????<li?v-for="(book, index) in books"?:key="index"?style="display:block">
          ????????{{index}}-{{book.name}}-{{book.author}}
          ??????</li>
          ????</ul>
          ????<!-- form to add a book -->
          ????<form?action="">
          ??????輸入書名:<input?type="text"?placeholder="book name"?v-model="inputBook.name"><br>
          ??????輸入作者:<input?type="text"?placeholder="book author"?v-model="inputBook.author"><br>
          ????</form>
          ????<button?type="submit"?@click="bookSubmit()">submit</button>
          ??</div>
          </template>

          <script>
          export?default?{
          ??name: 'HelloWorld',
          ??data () {
          ????return?{
          ??????msg: 'Welcome to Your Vue.js App',
          ??????// books list data
          ??????books: [
          ????????{name: 'test', author: 't'},
          ????????{name: 'test2', author: 't2'}
          ??????],
          ??????// book data in the form
          ??????inputBook: {
          ????????"name": "",
          ????????"author": "",
          ??????}
          ????}
          ??},
          ??methods: {
          ????loadBooks () {...}, // load books list when visit the page
          ????bookSubmit () {...} // add a book to backend when click the button
          ??},
          ??created: function?() {
          ????this.loadBooks()
          ??}
          }
          </script>
          ...


          啟動(dòng)前端項(xiàng)目,瀏覽器訪問(wèn)127.0.0.1:8080,可以看到剛寫的頁(yè)面已經(jīng)更新上去了,丑是丑了點(diǎn),意思到了就行~如下圖:

          f09c1dbc91394e2f2ee6413177178818.webp

          4.前后端聯(lián)調(diào)


          敲黑板,重點(diǎn)來(lái)了!!上面的頁(yè)面中數(shù)據(jù)其實(shí)是寫死在前端頁(yè)面的模擬數(shù)據(jù),這一節(jié)希望通過(guò)從后端拿數(shù)據(jù)并展示在前端頁(yè)面的方式來(lái)完成前后端聯(lián)調(diào)。前后端聯(lián)調(diào),涉及最多的就是跨域的問(wèn)題,為了保證安全,通常需要遵循同源策略,即“協(xié)議、域名、端口”三者都相同,具體可以看看相關(guān)的博客,這里只需知道上述三者相同才算同源即可。

          后端部分,對(duì)于django的跨域問(wèn)題,網(wǎng)上比較常用的做法就是利用django-cors-headers模塊來(lái)解決,這里也不能免俗,操作如下。

          先在命令行中進(jìn)行對(duì)應(yīng)模塊的安裝:??????

          pip install django-cors-headers


          然后在項(xiàng)目中添加該模塊:


          # books_demo/settings.py
          INSTALLED_APPS = [
          ????...
          ????# demo
          ????'corsheaders',
          ????...
          ]

          MIDDLEWARE = [
          ????'corsheaders.middleware.CorsMiddleware', # 需注意與其他中間件順序,這里放在最前面即可
          ????...
          ]

          # 支持跨域配置開始
          CORS_ORIGIN_ALLOW_ALL = True
          CORS_ALLOW_CREDENTIALS = True

          后端部分告于段落,接下來(lái)需要補(bǔ)充一下前端的邏輯,Vue框架現(xiàn)在一般都用axios模塊進(jìn)行網(wǎng)絡(luò)請(qǐng)求,這里沿用這種方式,下面是在前端項(xiàng)目中操作:

          首先命令行安裝axios模塊,如果沒有安裝cnpm就還是用npm安裝:

          cnpm install axios

          為了方便管理api請(qǐng)求的各種邏輯,在前端項(xiàng)目的src目錄下創(chuàng)建api目錄,然后創(chuàng)建api.js和index.js文件。index.js文件是對(duì)axios做配置:

          // appfront/src/api/index.js
          import?Vue from?'vue'
          import?Axios from?'axios'

          const?axiosInstance = Axios.create({
          ????withCredentials: true
          })

          // 通過(guò)攔截器處理csrf問(wèn)題,這里的正則和匹配下標(biāo)可能需要根據(jù)實(shí)際情況小改動(dòng)
          axiosInstance.interceptors.request.use((config) =>?{
          ????config.headers['X-Requested-With'] = 'XMLHttpRequest'
          ????const?regex = /.*csrftoken=([^;.]*).*$/
          ????config.headers['X-CSRFToken'] = document.cookie.match(regex) === null?? null?: document.cookie.match(regex)[1]
          ????return?config
          })

          axiosInstance.interceptors.response.use(
          ????response?=>?{
          ????????return?response
          ????},
          ????error?=>?{
          ????????return?Promise.reject(error)
          ????}
          )

          Vue.prototype.axios = axiosInstance

          export?default?axiosInstance

          api.js文件是對(duì)后端進(jìn)行請(qǐng)求,可以看到,獲取books列表和添加一本book各對(duì)應(yīng)一個(gè)請(qǐng)求:

          //?appfront/src/api/api.js
          import?axiosInstance from?'./index'

          const axios = axiosInstance

          export?const getBooks = ()?=>?{return?axios.get(`http://localhost:8000/api/books/`)}

          export?const postBook = (bookName, bookAuthor)?=>?{return?axios.post(`http://localhost:8000/api/books/`, {'name': bookName, 'author': bookAuthor})}


          然后更新HelloWorld.vue中的處理邏輯:


          // appfront/src/components/HelloWorld.vue
          <script>
          import?{getBooks, postBook} from?'../api/api.js'
          export?default?{
          ??...
          ??methods: {
          ????loadBooks () {
          ??????getBooks().then(response?=>?{
          ????????this.books = response.data
          ??????})
          ????}, // load books list when visit the page
          ????bookSubmit () {
          ??????postBook(this.inputBook.name, this.inputBook.author).then(response?=>?{
          ????????console.log(response)
          ????????this.loadBooks()
          ??????})
          ????} // add a book to backend when click the button
          ??},
          ??...
          }
          </script>

          至此,一個(gè)極其簡(jiǎn)陋的查詢和添加書籍的功能算是完成了~如下圖:

          07c11d334ff973415ab1cd890dc56183.webpb64fdd0246c94d04ffa0612fda75bfae.webp

          可以看到,列表里面的數(shù)據(jù)是從后端讀取到的,同時(shí)前端的提交數(shù)據(jù)庫(kù)也能有對(duì)應(yīng)的操作,所以前后端至此是打通了。

          5.打包??


          現(xiàn)階段是前后端分開開發(fā),但是當(dāng)最后要用的時(shí)候,還需要把代碼合在一起。

          首先對(duì)前端項(xiàng)目進(jìn)行打包,這里用Vue的自動(dòng)打包:

          npm run build

          可以看到前端項(xiàng)目中多出了一個(gè)dist文件夾,這個(gè)就是前端文件的打包結(jié)果。需要把dist文件夾復(fù)制到books_demo項(xiàng)目文件夾中。

          然后對(duì)settings.py文件進(jìn)行相應(yīng)的修改,其實(shí)就是幫django指定模版文件和靜態(tài)文件的搜索地址:

          # books_demo/books_demo/settings.py
          ...
          TEMPLATES = [
          ????{
          ????????'BACKEND': 'django.template.backends.django.DjangoTemplates',
          ????????'DIRS': [os.path.join(BASE_DIR, 'dist')], # demo add
          ????????...
          ????},
          ]
          ...
          STATICFILES_DIRS = [
          ????os.path.join(BASE_DIR, 'dist/static'),
          ]
          ..

          最后在根urls.py文件中配置一下入口html文件的對(duì)應(yīng)路由:

          # books_demo/books_demo/urls.py
          ...
          from?django.views.generic.base import?TemplateView

          urlpatterns = [
          ????...
          ????path('', TemplateView.as_view(template_name='index.html'))
          ]

          重新啟動(dòng)項(xiàng)目,這次用瀏覽器訪問(wèn)?127.0.0.1:8000?,即django服務(wù)的對(duì)應(yīng)端口即可。

          可以看到,項(xiàng)目的交互是正常的,符合我們的預(yù)期。

          總結(jié)


          本文以一個(gè)非常簡(jiǎn)單的demo為例,介紹了利用django+drf+vue的前后端分離開發(fā)模式,基本可以算是手把手入門。有了這個(gè)小demo之后,不管是前端頁(yè)面還是后端功能,都可以做相應(yīng)的擴(kuò)展,從而開發(fā)出更加復(fù)雜使用的網(wǎng)站。

          我們的文章到此就結(jié)束啦,如果你喜歡今天的Python 實(shí)戰(zhàn)教程,請(qǐng)持續(xù)關(guān)注Python實(shí)用寶典。

          有任何問(wèn)題,可以在公眾號(hào)后臺(tái)回復(fù):加群,回答相應(yīng)紅字驗(yàn)證信息,進(jìn)入互助群詢問(wèn)。

          原創(chuàng)不易,希望你能在下面點(diǎn)個(gè)贊和在看支持我繼續(xù)創(chuàng)作,謝謝!

          點(diǎn)擊下方閱讀原文可獲得更好的閱讀體驗(yàn)

          Python實(shí)用寶典?(pythondict.com)
          不只是一個(gè)寶典
          歡迎關(guān)注公眾號(hào):Python實(shí)用寶典

          瀏覽 64
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  熟妇一区 | 色色97| 免费抽插视频 | 欧美一级A片免费 | 韩国精品一二区 |