本章內容;css
1. FBV與CBVhtml
FBV: Function Base View前端
CBV:Class Base Viewpython
示例:git
from django.shortcuts import render, HttpResponse from django.http import JsonResponse # Create your views here. def index(request): if request.method == "POST": print(request.POST) # 修改數據庫 return HttpResponse("OK") return render(request, "index.html") # CBV from django import views class Index(views.View): def get(self, request): return render(request, 'index.html') def post(self, request): print(request.POST) return HttpResponse("OK") # def index2(request): # if request.method == "GET": # return render(request, "index.html") # print(request.POST) # # 修改數據庫 # return JsonResponse("OK") def ajax(request): return JsonResponse({"code": 0})
注意事項:github
1.CBV定義必定要繼承django.views.viewajax
2. 註冊路由的時候要寫 類名.as_view()數據庫
3.具體原理是:dispatch()方法 中利用反射 找到每一個請求執行django
1 from django import views 2 3 4 class Index(views.View): 5 def get(self, request): 6 return render(request, 'index.html') 7 8 def post(self, request): 9 print(request.POST) 10 return HttpResponse("OK")
狀態碼json
200 OK - [GET]:服務器成功返回用戶請求的數據,該操做是冪等的(Idempotent)。 201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數據成功。 202 Accepted - [*]:表示一個請求已經進入後臺排隊(異步任務) 204 NO CONTENT - [DELETE]:用戶刪除數據成功。 400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發出的請求有錯誤,服務器沒有進行新建或修改數據的操做,該操做是冪等的。 401 Unauthorized - [*]:表示用戶沒有權限(令牌、用戶名、密碼錯誤)。 403 Forbidden - [*] 表示用戶獲得受權(與401錯誤相對),可是訪問是被禁止的。 404 NOT FOUND - [*]:用戶發出的請求針對的是不存在的記錄,服務器沒有進行操做,該操做是冪等的。 406 Not Acceptable - [GET]:用戶請求的格式不可得(好比用戶請求JSON格式,可是隻有XML格式)。 410 Gone -[GET]:用戶請求的資源被永久刪除,且不會再獲得的。 422 Unprocesable entity - [POST/PUT/PATCH] 當建立一個對象時,發生一個驗證錯誤。 500 INTERNAL SERVER ERROR - [*]:服務器發生錯誤,用戶將沒法判斷髮出的請求是否成功。 更多看這裏:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
錯誤處理,狀態碼是4xx時,應返回錯誤信息,error當作key。
{ error: "Invalid API key" }
返回結果,針對不一樣操做,服務器向用戶返回的結果應該符合如下規範。
GET /collection:返回資源對象的列表(數組) GET /collection/resource:返回單個資源對象 POST /collection:返回新生成的資源對象 PUT /collection/resource:返回完整的資源對象 PATCH /collection/resource:返回完整的資源對象 DELETE /collection/resource:返回一個空文檔
Hypermedia API,RESTful API最好作到Hypermedia,即返回結果中提供連接,連向其餘API方法,使得用戶不查文檔,也知道下一步應該作什麼。
1
2
3
4
5
6
|
{
"link"
: {
"rel"
:
"collection https://www.example.com/zoos"
,
"href"
:
"https://api.example.com/zoos"
,
"title"
:
"List of zoos"
,
"type"
:
"application/vnd.yourformat+json"
}}
|
路由系統:
1
2
3
|
urlpatterns
=
[
url(r
'^users'
, Users.as_view()),
]
|
CBV視圖:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
from
django.views
import
View
from
django.http
import
JsonResponse
class
Users(View):
def
get(
self
, request,
*
args,
*
*
kwargs):
result
=
{
'status'
:
True
,
'data'
:
'response data'
}
return
JsonResponse(result, status
=
200
)
def
post(
self
, request,
*
args,
*
*
kwargs):
result
=
{
'status'
:
True
,
'data'
:
'response data'
}
return
JsonResponse(result, status
=
200
)
|
實驗案例:新聞系統
實現方式一:
1 from django.db import models 2 3 # Create your models here. 4 5 6 # 文章表 7 class Article(models.Model): 8 title = models.CharField(max_length=32) 9 # 文章發佈時間 10 # auto_now每次更新的時候會把當前時間保存 11 create_time = models.DateField(auto_now_add=True) 12 # auto_now_add 第一次建立的時候把當前時間保存 13 update_time = models.DateField(auto_now=True) 14 # 文章的類型 15 type = models.SmallIntegerField( 16 choices=((1, "原創"), (2, "轉載")), 17 default=1 18 ) 19 # 來源 20 school = models.ForeignKey(to='School', on_delete=models.CASCADE) 21 # 標籤 22 tag = models.ManyToManyField(to='Tag') 23 24 25 # 文章來源表 26 class School(models.Model): 27 name = models.CharField(max_length=16) 28 29 30 # 文章標籤表 31 class Tag(models.Model): 32 name = models.CharField(max_length=16)
執行命令:
migrate makemigrations
插入數據庫數據
以上有了數據信息,而後進行json API接口的方式展現
1 from django.contrib import admin 2 from django.urls import path 3 from app01 import views 4 5 urlpatterns = [ 6 path('admin/', admin.site.urls), 7 path('article_list/',views.article_list), 8 ]
from django.shortcuts import render,HttpResponse from app01 import models import json # Create your views here. def article_list(request): #去數據庫查詢全部的文章數據 quest_set = models.Article.objects.all().values("id","title") #values是字典,values_list是列表 #序列化成json格式 data = json.dumps(list(quest_set),ensure_ascii=False) #返回 return HttpResponse(data)
注意:json只支持7種數據類型,ORM查詢出來的結果爲QuerySet類型,它是不支持的。
日期對象也是不支持的,須要轉換爲字符串。
啓動django項目,訪問URL: http://127.0.0.1/article_list/,所以每個時間,都要轉換爲字符串,太麻煩了。
轉換方式:
1 from django.shortcuts import render,HttpResponse 2 from app01 import models 3 import json 4 5 # Create your views here. 6 def article_list(request): 7 #去數據庫查詢全部的文章數據 8 quest_set = models.Article.objects.all().values("id","title","create_time") #values是字典,values_list是列表 9 #序列化成json格式 10 11 #1.先把時間對象轉換成字符串格式 12 for i in quest_set: 13 i["create_time"] = i["create_time"].strftime('%Y-%m-%d') 14 15 data = json.dumps(list(quest_set), ensure_ascii=False) 16 #返回 17 return HttpResponse(data)
JsonResponse 對象:
class JsonResponse
(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None,**kwargs)
這個類是HttpRespon的子類,它主要和父類的區別在於:
1 from django.shortcuts import render,HttpResponse 2 from django.http import JsonResponse 3 from app01 import models 4 import json 5 6 # Create your views here. 7 #第二種方式 8 def article_list(request): 9 #去數據庫查詢全部的文章數據,返回queryset,每個元素都是字典 10 query_set = models.Article.objects.all().values("id","title","create_time","type","school") 11 print(query_set) 12 for i in query_set: 13 print(i) 14 15 #學校對象 16 school_obj = models.School.objects.filter(id=i['school']).first() 17 #學校id 18 id = school_obj.id 19 #學校的名字 20 name = school_obj.name 21 #修改字典,key爲school的值 22 i['school'] = {"id":id,"name":name} 23 24 #返回json對象,safe=False表示任何能轉換爲json格式的對象 25 return JsonResponse(list(query_set),safe=False)
查看JsonResponse源代碼
def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None, **kwargs): if safe and not isinstance(data, dict): raise TypeError( 'In order to allow non-dict objects to be serialized set the ' 'safe parameter to False.' ) if json_dumps_params is None: json_dumps_params = {} kwargs.setdefault('content_type', 'application/json') data = json.dumps(data, cls=encoder, **json_dumps_params) super(JsonResponse, self).__init__(content=data, **kwargs)
注意:從上面的代碼中,能夠看出。針對查詢對應的學校信息,使用了for循環。它是一個外鍵字段,
那若是再查詢一個外鍵字段呢?再來一個for循環?代碼太冗長了!
serializer 容許複雜數據(好比 querysets 和 model 實例)轉換成python數據類型,而後能夠更容易的轉換成 json 或 xml 等。同時,serializer也提供了反序列化功能,容許解析數據轉換成複雜數據類型。
中文文檔連接:
https://q1mi.github.io/Django-REST-framework-documentation/api-guide/serializers_zh/
class DBG(serializers.Serializer): # 聲明序列化器 id = serializers.IntegerField() title = serializers.CharField() create_time = serializers.DateField() type = serializers.IntegerField() school = serializers.CharField(source="school.name")
注意:source = "school.name" 表示school表中的name字段
可使用它來序列化和反序化與DBG對象相應的數據。
申明一個序列化看起來很是像申明一個form。咱們以前學習form組件時,將須要的字段類型都指定好了!
一般你會想要與Django模型相對應的序列化類。
ModelSerializer
類可以讓你自動建立一個具備模型中相應字段的Serializer
類。
這個ModelSerializer
類和常規的Serializer
類同樣,不一樣的是:
.create()
方法和.update()
方法。
聲明一個ModelSerializer
以下:
class CYM(serializers.ModelSerializer): type = serializers.CharField(source='get_type_display') class Meta: model = models.Article fields = "__all__" # ("id", "title", "type") depth = 1 # 官方推薦不超過10層
默認狀況下,全部的模型的字段都將映射到序列化器上相應的字段。
模型中任何關聯字段好比外鍵都將映射到PrimaryKeyRelatedField
字段。默認狀況下不包括反向關聯,除非像serializer relations文檔中規定的那樣顯示包含。
查看官方文檔
https://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.get_FOO_display
對於具備選擇集的每一個字段,該對象將具備一個get_FOO_display()方法,其中FOO是該字段的名稱。 此方法返回字段的「可讀」值。
source='get_type_display' 表獲取type字段中選擇集的值。
不懂?看一下models.py中的Article表,看這一段
# 文章的類型 type = models.SmallIntegerField( choices=((1, "原創"), (2, "轉載")), default=1 )
ORM是查詢表的數據,那麼這個type在真正存儲時,是1或2。
可是我想要獲得"原創"和"轉載",怎麼辦?那就須要我上面提到的get_type_display。
注意:type的變量名和字段名必須保持一致,那麼使用serializers後,結果集中type的值爲"原創"和"轉載",而不是1和2
model = models.Article 表示Article表
fields = "__all__" 表示全部字段,若是須要指定字段。能夠寫成這樣fields = ("id", "title", "type")
depth = 1 表示深度爲1層。有外鍵關聯時,才須要設置depth參數!
由於Article表和School表,是一對多的關係,它們之間的關係只有一層。假設說:School表和另一個表(簡稱B表)有關係。Article表經過School表,要去查詢B表的數據,那麼層數就是2,以此類推!
def article_list(request): # 查詢全部 # 去數據庫查詢全部的文章數據 query_set = models.Article.objects.all() xbg = CYM(query_set, many=True) print(xbg.data) # 返回 return JsonResponse(xbg.data, safe=False)
def article_list(request): # 查詢全部 # 去數據庫查詢全部的文章數據 query_set = models.Article.objects.all() xbg = CYM(query_set, many=True) print(xbg.data) # 返回 return JsonResponse(xbg.data, safe=False)
參數解釋:
many=True 表示能序列化多個對象。
什麼意思?article表有多條數據,每一條數據,就是一個對象。咱們須要查詢表的全部記錄,因此必須指定many=True。返回一條數據時,不須要指定many=True
views.py完整代碼以下:
from django.shortcuts import render,HttpResponse from django.http import JsonResponse from app01 import models import json from rest_framework import serializers # Create your views here. class DBG(serializers.Serializer): # 聲明序列化器 id = serializers.IntegerField() title = serializers.CharField() create_time = serializers.DateField() type = serializers.IntegerField() school = serializers.CharField(source="school.name") class CYM(serializers.ModelSerializer): # 聲明ModelSerializer # type = serializers.CharField(source='get_type_display') class Meta: model = models.Article fields = "__all__" # ("id", "title", "type") depth = 1 # 官方推薦不超過10層 def article_list(request): # 查詢全部 # 去數據庫查詢全部的文章數據 query_set = models.Article.objects.all() xbg = CYM(query_set, many=True) print(xbg.data) # 返回 return JsonResponse(xbg.data, safe=False)
能夠看到type的值不是數字,而是選擇集中的值,它作了替換。是下面這一行,作了替換
type = serializers.CharField(source='get_type_display')
school的值,也能顯示相關聯的數據。
CYM是通用的,能夠多條,也能夠一條。
注意:多條的時候,須要加參數many=True。而一條,則不用!
修改urls.py,增長一個路徑
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^article_list/', views.article_list), url(r'article_detail/(\d+)', views.article_detail), ]
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^article_list/', views.article_list), url(r'article_detail/(\d+)', views.article_detail), ]
修改views.py,增長視圖函數
from django.shortcuts import render,HttpResponse from django.http import JsonResponse from app01 import models import json from rest_framework import serializers # Create your views here. class DBG(serializers.Serializer): # 聲明序列化器 id = serializers.IntegerField() title = serializers.CharField() create_time = serializers.DateField() type = serializers.IntegerField() school = serializers.CharField(source="school.name") class CYM(serializers.ModelSerializer): # 聲明ModelSerializer # type = serializers.CharField(source='get_type_display') class Meta: model = models.Article fields = "__all__" # ("id", "title", "type") depth = 1 # 官方推薦不超過10層 def article_list(request): # 查詢全部 # 去數據庫查詢全部的文章數據 query_set = models.Article.objects.all() xbg = CYM(query_set, many=True) print(xbg.data) # 返回 return JsonResponse(xbg.data, safe=False) def article_detail(request, id): # 查詢單條數據 article_obj = models.Article.objects.filter(id=id).first() xcym = CYM(article_obj) return JsonResponse(xcym.data)
刷新頁面,訪問url: http://127.0.0.1:8000/article_detail/1
使用格式化工具,效果以下:
總結:
使用ORM對象轉換爲json對象時,推薦使用serializers
Postman一款很是流行的API調試工具。不只能夠調試簡單的css、html、腳本等簡單的網頁基本信息,它還可以發送任何類型的HTTP 請求 (GET, HEAD, POST, PUT..),附帶任何數量的參數+ headers。對於開發過程當中去調試接口,Postman確實足夠的簡單方便,並且功能強大。
官網地址:
使用windows安裝以後,打開主程序,跳過登陸
訪問文章列表 http://127.0.0.1:8000/article_list/
訪問文章詳情 http://127.0.0.1:8000/article_detail/1
總結:
1. 使用Django 的視圖 本身序列化 1. HttpResponse 2. JsonResponse 3. serializers 2. 使用Django REST Framework 框架的序列化工具類 1. 安裝 pip install djangorestframework 2. 導入 from rest_framework import serializers 3. 使用 class ArticleSerializer(serializers.Serializer): ...
有些狀況下,咱們須要使用python腳原本調用django,從而方便使用django提供的一些指令!
在django項目根目錄下建立文件test_orm.py,它和manage.py是同級的
import os if __name__ == "__main__": # 設置django環境 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_drf.settings") import django django.setup() from app01 import models obj = models.Article.objects.filter(id=1).values() print(obj)
執行腳本,輸出以下:
<QuerySet [{'title': 'Python三年用不上', 'id': 1, 'school_id': 1, 'type': 1, 'update_time': datetime.date(2018, 7, 31), 'create_time': datetime.date(2018, 7, 31)}]>
若是用戶主動退出,session會自動清除,若是沒有退出就一直保留,記錄數愈來愈大,要定時清理沒用的session。
django中已經提供了這個方法,推薦把它加入到crontab中自動清理過時的session,防止session表記錄過大,影響訪問速度。
python E:\python_script\django框架\day15\about_drf\manage.py clearsessions