DRF 與 React(Django2.1 + 測試 + xadmin + api文檔)-翻譯強化版

原文: valentinog.com/blog/tut

翻譯版實踐教程: Django Rest 與 React(Django2.1 加 一點小測試 加一點譯者的小額外功能)

最終構建了一個有後台管理 + 提供api服務 + Mysql資料庫 + 在線api文檔的Lead系統。

一個實用(自認為)的介紹: 實用Django REST 與 React,特性! Django2.1!

如今(可供開發選擇的)web框並不匱乏。

想要構建一個API服務? 這裡列舉出一些你可以立馬想到說出名字的: Laravel, Rails, Node.js and Koa 2, Phoenix。

但是擺在我們面前的現實是: 客戶想要一個儘可能快的原型,這時我該如何做?

我選擇了一個web 框架,他:

  • 讓我可以寫更少的代碼
  • 讓我可以儘可能遵循MVP模式
  • 為擴展項目提供了一個穩定的基礎

請信我! 當涉及到開發速度時,Django是很好的一個選擇。 但是如何去創建一個簡單的Django Rest API呢?如何去 組織構建 一個Django 項目 與 React呢?

不要害怕,我們將在下面的教程中一起探索。

目錄

  • Django REST with React: 我們將會學到什麼
  • Django REST with React: requirements(環境依賴)
  • Django REST with React: 為項目創建一個虛擬的 Python 環境
  • Django REST with React: 構建一個 Django 的 application
  • Django REST with React: 創建一個 Django Model(譯者增 GitHub 託管代碼)
  • Django REST with React: 一丟丟測試
  • Django REST with React: Django Rest serializers(序列化器)
  • Django REST with React: 設置視圖控制器
  • Django REST with React: 設置urls 路由
  • Django REST with React: (seeding)餵養資料庫
  • Django REST with React: Django 與 React 協同
  • Django REST with React: 構建 React 與 webpack
  • Django REST with React: React 前端
  • Django REST with React: 前端測試
  • Django REST with React: 構建一個React 表單
  • Django REST with React: 總結
  • Django REST with React: 資源

Django REST with React: 我們將會學到什麼

在下面的教程中你將會學到:

  • 如何構建一個簡單的 Django REST API
  • 如何組織構建一個 Django project 與 React

我們將要做個啥嘞? 在這個項目里,我們將會構建一個簡單的 API 來列出並存儲領導。

Django REST with React: requirements(環境依賴)

為了能繼續跟進下面的教程,你應該擁有:

  • 掌握 Python 與 Django 基礎
  • 掌握 JavaScript ES6 和 React 基礎
  • 在你的電腦系統中安裝一個新版本的 Node.js

準備好了?讓我們一起出發吧!

Django REST with React: 為項目創建一個虛擬的Python環境

首要的是來確認你擁有一個虛擬的Python環境,你可以在Python3中使用 pipenv,pyenv,或者venv模塊。 (譯者推薦使用pipenv)

pip install pipenv
mkdir django-drf-react-quickstart && cd django-drf-react-quickstart
pipenv shell

然後安裝依賴: 安裝Django 和 Django REST framework 通過下面命令:

pipenv install django djangorestframework

當安裝結束,你可以通過下面命令創建一個新的Django 項目:

django-admin startproject drf_react .

現在我們可以開始構建我們的第一個Django app 來 列出與存儲leads

Django REST with React: 構建一個Django的application

一個Django項目包含許多的 applications(應用)。理想狀態下 每個應用應該只做一件事。

Django applications(應用) 是模塊化的,可重用的。 例如: 我創建了一個lead 應用用來創建和列出領導。

如果其他項目需要一個相同的app,我可以通過 package manager(INSTALLED_APPS) 來安裝leads。嗯,沒錯,這就是全部。

我建議去閱讀 How to write reusable apps,並觀看 DjangoCon 2008: Reusable Apps 來學習關於app的最佳實踐。

在Django中創建一個新的application,你應該運行:

django-admin startapp app_name

為了在項目的文件夾中創建leads app:

cd django-drf-react-quickstart

然後初始化我們的app:

django-admin startapp leads

注意: 我需要假設你位於 /YOUR_CODE_DIR/django-drf-react-quickstart/來運行的上述命令! 以及這些命令是在pipenv shell啟動的虛擬環境下執行的。

你將看到一個新的名字為leads的文件夾,在你的/YOUR_CODE_DIR/django-drf-react-quickstart/目錄中。

就像上圖這樣。

現在讓我們告訴Django如何使用這個新的app

打開 ./drf_react/settings.py 並添加這個app在 INSTALLED_APPS中:

INSTALLED_APPS = [
django.contrib.admin,
django.contrib.auth,
django.contrib.contenttypes,
django.contrib.sessions,
django.contrib.messages,
django.contrib.staticfiles,
leads, # 添加leads app
]

到目前為止一切順利。

譯者附加教程(GitHub管理代碼)

  • GitHub 新建Repo

  • GitHub 奪命N連環

# 起手式
git init
# 添加當前文件進入式
git add .
# commit文件式
git commit -m "初始化項目目錄,添加leads app"
# 設置要上哪個雲端式
git remote add origin https://github.com/mtianyan/django-drf-react-quickstart.git
# 把網頁新建拉下來式
git pull --rebase origin master
# push真的上雲式
git push --set-upstream origin master

首次使用才如上面N連環般麻煩。

  • GitHub 奪命三全

# 第一全,文件全添加
git add .
# 第二全,commit信息要全
git commit -m "巴啦啦小魔仙balala"
# 第三全,全網速推上雲
git push

Django REST with React: 創建一個Django Model

注意: 在進行下一步之前,請確保你仍然位於: /YOUR_CODE_DIR/django-drf-react-quickstart/

隨著app的安裝,我們是時候來創建我們的第一個model了,一個model 是一個對象用來表示你的表數據。幾乎每個web 框架都擁有models這個概念。 Django 也不例外。

一個Django模型可以擁有一個或多個欄位: 每個欄位是你數據表中的一列,當進行下一步之前,讓我們為我們的lead app 定義它的依賴。

首先我們需要一個 Lead model

由於我收集了leads的信息,我認為一個Lead model 應該擁有以下欄位:

  • 一個名字
  • 一個郵件
  • 一個信息

(感覺添加額外的欄位也很輕鬆,例如我們想再加個手機號)

請不要忘記一個 時間戳 欄位! Django 不會默認的為你添加一個 created_at 列。

很好!

打開 ./leads/models.py然後創建Lead model:

from django.db import models
class Lead(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
message = models.CharField(max_length=300)
created_at = models.DateTimeField(auto_now_add=True)

這裡有一個關於models的快速指南: 花時間看看 -> Django fields documentation

當計劃一個model時,請儘力選擇對於你的案例最適合的那些欄位。

(譯者)附加使用mysql及本地化時間等

pipenv install mysqlclient

新建一個mysql資料庫

settings -> 修改為使用mysql資料庫:

DATABASES = {
default: {
ENGINE: django.db.backends.mysql,
NAME: drf_react,
USER: root,
PASSWORD: 密碼,
HOST:127.0.0.1

}
}

settings -> 設置本地化

# 語言改為中文
LANGUAGE_CODE = zh-hans

# 時區改為上海
TIME_ZONE = Asia/Shanghai

USE_I18N = True

USE_L10N = True

# 資料庫存儲使用時間,True時間會被存為UTC的時間
USE_TZ = False

在model定義就位之後,讓我們一起創建一個migration(遷移) 通過運行:

python manage.py makemigrations leads

並最終 migrate 到資料庫使用下面命令:

python manage.py migrate

可以看到mysql中生成的表:

非常棒, 下一小節我們將討論序列化器和試圖,但是首先我們需要一點小小的測試。

Django REST with React: 一丟丟測試

此時此刻,你或許在驚嘆"Valentino(作者名), 咋測試這個app"

不會讓TDD(測試驅動開發) 教程來把你搞崩潰,我將給你一些小技巧(tips)

我見過大量的Django 教程里都是這樣開始寫的:

class SomeModelModelTest(TestCase):
def setUp(self):
SomeModel.objects.create(
name=fake.name(),
email=fake.email(),
phone=fake.phone_number(),
message=fake.text(),
source=fake.url()
)
def test_save_model(self):
saved_models = SomeModel.objects.count()
self.assertEqual(saved_models, 2)

不要這樣做,這對於測試Django model 或 Django ORM 都是沒踩對點的(沒啥用的)。

對於Django里的測試,這裡有一個好的出發點:

  • 不要測試 Django 的內建代碼(models views 等)
  • 不要測試 Python 的內建函數

總的來說: 不要測試那些已經被測試過的!

那我該測些啥呢? 你是否在Django的model中添加了一個 custom method(自定義的方法)? 測它!

你是否有一個custom view(自定義的視圖)呢? 測它! 但是我怎麼知道要去測試啥呢?

通過安裝工具 coverage 來幫自己一點忙

pipenv install coverage

然後,每當你添加一些代碼到你的應用時,運行coverage:

coverage run --source=. manage.py test

然後會產生報告:

coverage html

用瀏覽器打開 /YOUR_CODE_DIR/django-drf-react-quickstart/htmlcov/index.html,你將看到你需要測試啥。

如果你更想在命令行里看到測試報告,你可以運行:

coverage report

等會! 你堅持看到了這? 我感動死了。

不要停! 緊緊抱住我的大腿, 下一節我們將看看序列化器(serializers)!

breakpoint: 奪命三全 -> push

Django REST with React: Django Rest serializers(序列化器)

注意: 開始下面之前,請確保你仍然在/YOUR_CODE_DIR/django-drf-react-quickstart/ 目錄。

什麼是序列化? 什麼是Django REST 序列器?

序列化是轉換一個對象到另一種數據格式的一種動作。在對象轉換完成後,我們可以將它保存到文件,或者在互聯網中發送它。

為什麼序列化如此必要呢?

思考一個Django model: 它是一個Python的嘞, 你該如何在瀏覽器中渲染一個Python的類到JSON 呢?

使用Django REST 序列器!

一個序列器 也可以反向工作: 它轉換 JSON 到 對象

這種方式你可以:

  • 通過轉換Django的models到JSON,來在瀏覽器中查看它們。
  • 製作 一個JSON 負載的 CURD(增刪改查) 的請求到API

簡要概括: DjangoREST 序列器 是操作模型到API的主宰。

創建一個新文件: ./leads/serializers.py. 這個LeadSerializer 接收我們的Lead model 與一些欄位

from rest_framework import serializers
from leads.models import Lead
class LeadSerializer(serializers.ModelSerializer):
class Meta:
model = Lead
fields = (id, name, email, message)

就像上面你能看到的代碼里那樣,我們繼承了ModelSerializer。

一個 ModelSerializer 在Django REST中就像一個 ModelForm

它非常適合於,任何你想接近 映射一個Model 到 一個Serializer 中時。

除了明確的定義需要映射的欄位,你也可以映射model中的所有欄位。

from rest_framework import serializers
from leads.models import Lead
class LeadSerializer(serializers.ModelSerializer):
class Meta:
model = Lead
fields = __all__

保存並關閉文件,我們離完成app更近了一步。

下面的章節里,我們將看一下 views(視圖) 和 urls。

Django REST with React: 設置視圖控制器

注意: 開始下面之前,請確保你仍然在/YOUR_CODE_DIR/django-drf-react-quickstart/ 目錄。

如果你從其他框架轉到Django,你可能感到驚奇的是: Django 沒有控制器!

控制器用來封裝處理 request 請求的邏輯並返回response。傳統的MVC 體系 包含 Model(模型), View(視圖), Controller(控制器)

這樣的MVC框架有: Rails, Phoenix, Laravel。

Django 是一個 MVT framework,它有的三層是: Model(模型) - View (視圖) - Template(模板)。其中View(視圖) 關注著請求和響應的一整個生命周期。

Django中很多類型的views: function views 函數視圖, class based views 基於類的視圖, and generic views 通用視圖.

雖然很多開發者相對於class based views(基於類的視圖)更喜歡 function views (函數視圖),但我是後者(基於類)的一個大粉絲

當我選擇Django,因為我的核心價值要求是: 開發速度,DRY(dont repeat yourself),更少的代碼。

當已經存在一組合理的默認值時,我認為繼續手寫Code是沒有意義的。

這是我的經驗法則:

僅當我們想要自定義通用視圖所花費的時間超過手動編寫視圖所花費的時間時,才使用函數視圖。

與簡單的Django一樣,在Django REST 框架中,有很多方法可以編寫視圖:

  • function based views(基於函數的視圖)
  • class based views(基於類的視圖)
  • generic API views(通用的API 視圖)

在這個教程的範圍內,我將使用 generic API view,目的是為了寫更少的代碼。

我們的簡單app應該有:

  • 列出模型中的集合
  • 創建一個新的對象到資料庫中

通過閱讀generic API views documentation 我們可以看到一件提供給我們一個可以用於列出和創建models的view。

它就是 ListCreateAPIView

ListCreateAPIView 接收一個queryset 和 一個序列化類作為參數。

打開 ./leads/views.py 創建視圖:

from leads.models import Lead
from leads.serializers import LeadSerializer
from rest_framework import generics
class LeadListCreate(generics.ListCreateAPIView):
queryset = Lead.objects.all()
serializer_class = LeadSerializer

通過三行代碼我們創建了一個可以處理GET 和 POST請求的view。

現在還缺點啥呢? URL 映射! 換句話說,我們需要映射URLs 到 視圖

咋整? 敬請期待下一節

Django REST with React: 設置urls 路由

注意: 開始下面之前,請確保你仍然在/YOUR_CODE_DIR/django-drf-react-quickstart/ 目錄。

來自Rails, Phoenix, or Laravel 的朋友們,你可能又感到驚訝了,Django竟然沒有路由配置。

雖然DRF 提出了 resourceful router 資源化的路由,但最簡單的映射URl到視圖的方式還是URL mapping。

我們的目標是聯通 LeadListCreate 到 api/lead/

換句話講,我們想要製作一個GET 和 POST請求到api/lead/ 來 列出和創建models。

./drf_react/urls.py配置URL mapping 包含app(leads)中的urls

from django.urls import path, include
urlpatterns = [
path(, include(leads.urls)),
]

下一步是創建一個新的文件: ./leads/urls.py:

from django.urls import path
from . import views
urlpatterns = [
path(api/lead/, views.LeadListCreate.as_view() ),
]

最後: 我們要讓 rest_framework 註冊進 INSTALLED_APPS。

打開 ./drf_react/settings.py 然後添加app 進入INSTALLED_APPS。

INSTALLED_APPS = [
django.contrib.admin,
django.contrib.auth,
django.contrib.contenttypes,
django.contrib.sessions,
django.contrib.messages,
django.contrib.staticfiles,
leads,
rest_framework # 加入 rest framework
]

此時你應該可以通過健全性檢查:

python manage.py runserver

訪問: 127.0.0.1:8000/api/lead 你將會看到 browsable API 可瀏覽式api

此時你可以通過網頁上內建的表單來創建一些數據

在下一節中,我們將學習如何在Django 中餵養資料庫(-v-)

Django REST with React: (seeding)餵養資料庫

注意: 開始下面之前,請確保你仍然在/YOUR_CODE_DIR/django-drf-react-quickstart/ 目錄。

你可以使用 Django fixtures 來填充資料庫。

當你想要給前端一些demo數據時,Fixtures時非常有用的。

創建一個新文件夾: ./leads/fixtures

然後創建一個新的文件: ./leads/fixtures/leads.json 內容為下面的JSON:

[
{
"model": "leads.lead",
"pk": 1,
"fields": {
"name": "mtianyan",
"email": "1147727180@qq.com",
"message": "I am a happy pythoner",
"created_at": "2019-01-07 00:00:00"
}
},
{
"model": "leads.lead",
"pk": 2,
"fields": {
"name": "Tom",
"email": "tomsomething@gmail.com",
"message": "I want to talk about a Python project",
"created_at": "2018-01-14 00:00:00"
}
}
]

保存並關閉這個文件,然後使用下面命令載入fixture:

python manage.py loaddata leads

這就是全部了,下面的部分,我們將實現一個簡單的React 前端!

譯者添加: xadmin 管理 & drf 在線文檔

安裝

pipenv install https://codeload.github.com/sshwsfc/xadmin/zip/django2

註冊進INSTALL_APP

INSTALLED_APPS = [
django.contrib.admin,
django.contrib.auth,
django.contrib.contenttypes,
django.contrib.sessions,
django.contrib.messages,
django.contrib.staticfiles,
leads, # 添加leads app
rest_framework, # 添加rest framework
xadmin, # 添加 xadmin
crispy_forms, # 添加 xadmin
]

配置URL(django-drf-react-quickstartdrf_reacturls.py):

from django.urls import path, include
import xadmin

urlpatterns = [
path(, include(leads.urls)),
path(xadmin/, xadmin.site.urls),
]

添加了xadmin的import 和 xadmin path url mapping。

新建adminx.py(django-drf-react-quickstartleadsadaminx.py)

import xadmin
from xadmin import views
from .models import Lead
class BaseSetting(object):
"""xadmin的基礎信息配置"""
enable_themes = True # 開啟主題功能
use_bootswatch = True

class GlobalSettings(object):
"""xadmin通用信息配置"""
site_title = "Leads Xadmin"
site_footer = "mtianyan@qq.com"

# 註冊設置信息到View
xadmin.site.register(views.BaseAdminView, BaseSetting)
xadmin.site.register(views.CommAdminView, GlobalSettings)

class LeadAdmin(object):
"""
list_display: 後台展示哪些欄位
search_fields: 後台可搜索哪些欄位
list_filter: 後台過濾器可使用哪些欄位
"""
list_display = [name, email,message]
search_fields = [name, email,message]
list_filter = [name, email,message,created_at]

xadmin.site.register(Lead, LeadAdmin)

遷移資料庫:

python manage.py makemigrations
python manage.py migrate

創建後台管理員

python manage.py createsuperuser

登錄後台

運行

python manage.py runserver

訪問: 127.0.0.1:8000/xadmin/

在線api交互文檔

  • 安裝需要的包:

pipenv install coreapi

  • 配置url(django-drf-react-quickstartdrf_reacturls.py)

from django.urls import path, include
import xadmin
from rest_framework.documentation import include_docs_urls # new

urlpatterns = [
path(, include(leads.urls)),
path(xadmin/, xadmin.site.urls),
path(api/docs/, include_docs_urls(title=Lead 在線API文檔)), # new
]

  • 添加註釋以便在線文檔生成

models.py

from django.db import models

# Create your models here.
class Lead(models.Model):
name = models.CharField(max_length=100,verbose_name="lead名字", help_text="lead名字")
email = models.EmailField(verbose_name="郵箱", help_text="郵箱")
message = models.CharField(max_length=300, verbose_name="信息", help_text="信息")
created_at = models.DateTimeField(auto_now_add=True,verbose_name="創建時間", help_text="創建時間")

添加verbose_name用於xadmin,help_text用於drf

views.py

class LeadListCreate(generics.ListCreateAPIView):
"""
get:
返回所有已存在的lead對象的列表

post:
創建一個新的lead實例
"""
queryset = Lead.objects.all()
serializer_class = LeadSerializer

  • 運行:

python manage.py runserver

訪問: 127.0.0.1:8000/api/docs

大功告成: 我們有了一個既有後台,又提供api,又有在線API文檔的Lead服務啦。

敬請期待下次更新React篇! 敬請期待下次更新React篇! 敬請期待下次更新React篇!


推薦閱讀:

TAG:Python | Django(框架) |