本身一是想跟上潮流二是習慣於直接幹三是沒有人能夠請教,因爲這三點常常搞得要死要活。以前只簡單看過沒寫過Diango,沒看過Django REST framework,今天一步到位直接上又撞上了南牆。在此記一下以備忘,也但願對後來者能有所幫助。本文至關於Django REST framework官方文檔的從新實現。html
Django是當下流行的一個python語言的web框架,相似於java的struts2,(若是struts2太舊不懂那也能夠理解爲spring boot)。前端
Django相似於struts2,也就是說其是mvc模式的,也就是說其v是先後端強耦合的,但如今都講REST。java
Django REST framework就是Django的REST化庫,用於實現Django的REST化。python
參見:http://www.javashuo.com/article/p-zlffrzyv-gd.htmlweb
依次點開pycharm----菜單----file----settings----project----project interpreter,安裝django、djangorestframework、pygments、pytest四個包spring
djangorestframework在conda-forge源中,若是找不到djangorestframework那應該是沒添加conda-forge源的緣由(中科大:https://mirrors.ustc.edu.cn/anaconda/cloud/conda-forge/)sql
或者經過系統菜單開啓「Anaconda Prompt」用pip安裝,命令以下shell
conda activate DjangoTest pip install django pip install djangorestframework pip install pygments pip install pytest
在前面中咱們已經建立了名稱爲DjangoTest的項目,但要注意只是咱們把名字命名爲DjangoTest而已改項目到如今爲止其實與Django無關。數據庫
Django項目須要經過django-admin命令來建立;因此咱們要到項目所在文件夾下將現有DjangoTest文件夾刪掉,而後用django-admin命令來從新建立DjangoTest。django
(前邊建立的DjangoTest的意義,是更可能是爲了建立DjangoTest虛擬環境。雖然有點繞,但這是我針對Scrapy和Django這種雞和蛋問題能想到的最好辦法)
而django-admin命令的位置,咱們能夠藉助conda env list來查看DjangoTest虛擬環境所在的目錄,而後加上\Scripts\django-admin.exe便是其位置。好比個人操做以下:
cd F:\PycharmProjects F: rmdir /s /q DjangoTest conda env list D:\Language\Miniconda3\envs\DjangoTest\Scripts\django-admin.exe startproject DjangoTest
建立完成後目錄結構以下:
django項目須要經過python manage.py runserver形式運行,咱們也須要配置成該形式。
依次點擊菜單----Run----Edit Configurations----左上角+號----Python,添加運行環境
Name----環境名稱,本身隨便填
Script path----manage.py所在的路徑,改爲本身的
Parameters----runserver,ip和端口若是須要直接追加在後邊便可
必定要注意,後續不要隨便在一個頁面就右鍵run/debug,而是無論修改什麼文件在什麼位置都要run/debug上邊這個環境,否則運行不起來。(一直報錯django.core.exceptions.ImproperlyConfigured: Requested setting INSTALLED_APPS, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.)
上邊咱們建立了Django項目,至於Django REST framework只是安裝並無開始操做,下邊咱們開始使用Django REST framework對上邊的Django項目進行REST化改造。
通常而言咱們不直接大幅修改Django項目的文件,而是新建一個APP實現REST,而後原來的Django項目文件只寫一些包含命令便可。所謂APP能夠理解爲子文件夾或者一個新線程。
爲了更好地證實咱們的程序是能很好運行的,我這裏會改用和官方例子不同的名稱包括app名稱model名稱等;並儘量說明每一個操做本質是在作什麼。
首先,進入到manage.py所在目錄新建一個app(注意打開的cmd中的python和pycharm中的python同爲python3否則運行就報錯了,我這裏直接在前邊的Anaconda Prompt中運行):
python manage.py startapp drest
向Django項目註冊drest,因爲Django REST framework其實也以app形式注入因此也一同註冊。編緝DjangoTest/settings.py找到INSTALLED_APPS追加如下內容:
'rest_framework', 'drest.apps.DrestConfig',
在drest目錄下新建urls.py(內容先不寫),而後在DjangoTest/usrls.py中包含它;即DjangoTest/usrls.py修改以下:
from django.contrib import admin from django.urls import path from django.conf.urls import url, include urlpatterns = [ path('admin/', admin.site.urls), url(r'^', include('drest.urls')), ]
另外咱們再在drest建立一個序列化文件serializers.py(內容先不寫)用於後續序列化。到此咱們的環境算搭建好了,項目目錄結構以下:
前邊咱們已搭好了環境,建立了一個app----drest,這裏咱們即在drest上進行開發。
這裏的model不是mvc中的m,而是orm中的表對應的類,稍後數據庫的表就是根據這個類來創建的。
編緝drest/model.py,寫入如下內容:
from django.db import models # Create your models here. class Test(models.Model): # 這些在建立數據表時是表字段,括號內爲字段對應屬性 # 不過注意default屬性,是說在實例化這個類時該字段默認是這個值,建立數據表時並不會看成一行括入數據表 created = models.DateTimeField(auto_now_add=True) username = models.CharField(max_length=100, default='ls', ) password = models.CharField(max_length=100, default='toor', ) class Meta: # 這個表示數據表的內容按建立時間排序 ordering = ('created',)
編寫drest/serializers.py寫入如下內容:
from rest_framework import serializers from drest.models import Test class TestSerializer(serializers.ModelSerializer): class Meta: # 此處指明本序列化對應的model model = Test # 此處指明從model對應數據表中讀出哪些字段 # id字段咱們在model中並沒指明應該是框架本身建立的 # 另外咱們還建立了created字段,但這裏咱們不加讀取他,固然你要讀取加上便可 fields = ('id', 'username', 'password')
編緝drest/urls.py,寫入如下內容:
from django.conf.urls import url from drest import views urlpatterns = [ url(r'^test/$', views.test), ]
在REST中視圖已經不是mvc中的html與後端代碼混淆的那種.jsp或.aspx頁面了,所指的是生成並返回json/xml結果的東西(反而更像mvc中的m)。
在路由中咱們設定連接test,指向test視圖;咱們這裏來實現test視圖,該視圖使用3.2中的序列化類讀取3.1中對應的數據表的全部內容實現序列化並返回。
from django.http import JsonResponse from rest_framework.parsers import JSONParser from drest.serializers import Test from drest.serializers import TestSerializer def test(request): """ List all code snippets, or create a new snippet. """ if request.method == 'GET':# 這裏應該是model對應的全部字段 test_obj = Test.objects.all() # 序列化 serializer = TestSerializer(test_obj, many=True) # 返回 return JsonResponse(serializer.data, safe=False) # 此框架想實現原始REST的思想,若是是post就保存到數據庫,這裏暫且保留雖然我以爲不實用 elif request.method == 'POST': data = JSONParser().parse(request) serializer = TestSerializer(data=data) if serializer.is_valid(): serializer.save() return JsonResponse(serializer.data, status=201) return JsonResponse(serializer.errors, status=400)
在沒有if代碼對get/post等方法都進行一樣的響應,若是要區分那就在在如if request.method == 'POST':分支內編寫響應代碼便可。爲方便post測試附上requests和curl post提交的形式。
requests post提交json:
import requests url = "http://127.0.0.1:8000/test1/" data = {"username":"ls", "password":"toor"} requests.post(url,json=data)
curl post提交json:
curl -H "Content-Type:application/json" -X POST --data '{"username": "ls","password":"toor"}' http://127.0.0.1:8000/test1/
咱們在3.1中就建好了model,在官方文檔中都是建好model就建對應數據表的,可是因爲我對實現步驟作了調整若是在3.1中就建表,會因程序有錯誤而建立失敗,因此咱們只能到這裏才建立類據表。
指示在數據庫中建立model對應的表,進入到manage.py目錄執行如下命令:
python manage.py makemigrations drest
python manage.py migrate
執行完成後在manage.py同級目錄下能夠看到一個db.sqlite3文件,該文件是一個sqlite3數據庫。
使用SQLiteStudio等工具打開,能夠看到有一個dres_test的表其字段「created」、「username」、「password」正是咱們在model中配置好的。
咱們一直說TestSerializer的做用是讀取drest_test表的全部內容並序列化,在上一步中咱們建立好了drest_test;可是咱們在model的註釋中也說過建立數據表時不會向表中插入數據,也就是說此時drest_test表雖建立好了但其是一個空表是沒數據的,此時若是咱們運行程序並訪問test連接那返回是空值。因此咱們要向drest_test表中插入數據。
進入到manage.py目錄執行如下命令啓動shell:
python manage.py shell
爲了更好地說明model中default的做用咱們插入兩條數據:
from drest.models import Test from drest.serializers import TestSerializer from rest_framework.renderers import JSONRenderer from rest_framework.parsers import JSONParser test = Test() test.save() test = Test(username='root') test.save()
此時查看drest_test表的內容,以下所示正是咱們插入的兩條數據:
咱們前面說過運行django項目run的必定要是咱們2.5中設置的運行環境,如今雖加項目進行了如些複雜的操做但項目仍是django項目仍是要運行那個環境(名爲django)。
pycharm切換到manage.py----在其上右鍵----選擇Run ‘django’,程序成功運行以下:
咱們看到監聽地址爲http://127.0.0.1:8000/,而咱們設置的路由是test
打開瀏覽器訪問http://127.0.0.1:8000/test,結果以下圖,返回結果與預期徹底一致:
上一大節的示例依據官方示例整理而成,整個流程雖然還算清楚,但給人一種複雜感。
好比爲何必定要我建立model、爲何必定要我建立model序列化類、爲何必定要建立數據表、爲何必定要向數據表中插入數據----總而言之,爲何必定要涉及數據庫?
並不是全部請求都要涉及數據庫的,或者我就只想一個請求過來而後直接簡單地返回隨便一個數,那該如何寫呢。以test1請求爲例。
編緝drest/urls.py,寫入如下內容:
from django.conf.urls import url from drest import views urlpatterns = [ url(r'^test1/$', views.test1), ]
編緝drest/views.py追加test1方法:
def test1(request): # 要獲取客戶端提交的參數,可經過request.GET["param_name"]或request.POST["param_name"]獲取,param_name是要獲取的參數名 # 但要另外注意對post提交django默認是有csrf token校驗的,要注意怎麼處理好,最簡單的方法是到setting.py中將'django.middleware.csrf.CsrfViewMiddleware'項註釋掉 # username = request.GET["username"] # username = request.POST["username"] # 若是前端經過json格式提交,那麼須要使用如下方式獲取參數 # data = JSONParser().parse(request) # username = data["username"] # Django執行sql語句,第一種方法是依賴model的model.objects.get()等方法 # 獲取第一條記錄 # Test.objects.get(username="ls") # 獲取記錄集合 # Test.objects.filter(username="ls") # Django執行sql語句,第二種方法是直接執行sql語句 # cursor = connection.cursor() # cursor.execute('select * from drest_test') # 獲取第一條記錄 # row = cursor.fetchone() # 遍歷數據表全部記錄 # for row in cursor.fetchall(): # print(f"{row}") dict1 = {} dict1["id"] = 1 dict1["result"] = "success" # JsonResponse()最正規的就是給他傳一個字典 # 上一節傳的serializer.data是一個列表反而不那麼正規,傳非字典參數要設置safe=False return JsonResponse(dict1)
和3.7同樣運行manage.py,而後訪問http://127.0.0.1:8000/test1/,結果以下圖。
英文水平通常加上沒用過Django也沒寫過REST,因此費了點周章但總算是完成了。
在第三大節上,網上現有的不少教和感受就是本身把英文版翻譯成中文,但又不能很好地解框架到底在作什麼,尤爲是model實際上是用來建立數據表和序列化類本質是讀取數據表的內容並返回這兩點,致使翻譯得似是而非反而讓人更難理解框架的本質。
如第四大節所言,咱們寫程序工做總不會都是讀取數據庫表而後返回。增刪改查尤爲是跨數據表的增刪改查仍是得在dao層中另行實現,做爲竄聯的邏輯代碼則在view上實現;view調用dao,dao調用model。
參考:
https://www.runoob.com/django/django-tutorial.html
https://www.django-rest-framework.org/tutorial/1-serialization/
https://stackoverflow.com/questions/28241203/objects-all-not-returning-any-objects-in-django