2018-08-02 1. 內容回顧 1. Serializer(序列化) 1. ORM對應的query_set和ORM對象轉換成JSON格式的數據 1. 在序列化類中定義自定義的字段:SerializerMethodField 在類中定義 get_自定義字段名(self, obj)方法 2. read_only 只在顯示(查詢)時纔會有效。 2. 對前端POST過來的數據作有效性的校驗 1. 必定要將數據以data=的形式傳遞到序列化類中!!! ser_obj = CommentSerializer(data=comment_data) 2. 判斷數據是否有效 ser_obj.is_valid(): 欠一個源碼 ser_obj.validated_data 中保存通過校驗的有效數據 3. 局部鉤子 定義一個validate_字段名(self, value) 4. 全局鉤子 定義一個validate方法 3. .save()方法將符合要求的數據存入數據庫 1. 本質上仍是調用ORM的create()方法 類名.objects.create(**ser_obj.validated_data) 2. 超連接的序列化 1. 超鏈接字段的三個參數 # 文章超連接序列化 class ArticleHyperLinkedSerializer(serializers.HyperlinkedModelSerializer): # view_name參數 默認使用 表名-detail # lookup_url_kwarg參數 默認使用pk,指的是反向生成URL的時候 路由中的分組命名匹配的key # lookup_field參數 默認使用的pk, 指的是反向生成URL的時候, 路由中分組命名匹配的value school = serializers.HyperlinkedIdentityField( view_name='school-detail111', lookup_url_kwarg='name', lookup_field='school_name' ) 2. 想要生成完整的超連接API,在序列化的時候還要傳入 context={'request': request} ser_obj = app01_serializers.ArticleHyperLinkedSerializer(all_article, many=True, context={'request': request}) 1. 想要生成相對路徑 context={'request': None} 2. 今日內容 1. 面向對象的三大特性 1. 封裝 1. 把共有的數據當成一類物體的屬性 2. 把共有的功能當成一類物體的方法 2. 繼承 1. 把共有的屬性或方法抽離出來放到一個基類(父類)中 3. 多態 1. 不一樣的物體調用同一個方法有不一樣的效果 Python中數字的+和字符串的+ 2. 葫蘆娃的故事 五個娃 ↓ 奇數娃和偶數娃 ↓ 套娃 3. GenericAPIView和五個混合類的組合使用 4. RetrieveUpdateDestroyAPIView和ListCreateAPIView的使用 5. ModelViewSet的使用 6. ModelViewSet Router的使用
在Django REST Framework中內置的Request類擴展了Django中的Request類,實現了不少方便的功能--如請求數據解析和認證等。css
好比,區別於Django中的request從request.GET中獲取URL參數,從request.POST中取某些狀況下的POST數據。html
在APIView中封裝的request,就實現了請求數據的解析:前端
對於GET請求的參數咱們經過request.query_params來獲取。python
對於POST請求、PUT請求的數據咱們經過request.data來獲取。jquery
1. 把共有的數據當成一類物體的屬性
2. 把共有的功能當成一類物體的方法git
1. 把共有的屬性或方法抽離出來放到一個基類(父類)中github
1. 不一樣的物體調用同一個方法有不一樣的效果
好比:Python中數字的+和字符串的+,結果是不同的。前者是計算,後者是拼接!ajax
先來列舉前5個娃,爲啥是5個呢?到最後,你就知道了!數據庫
""" 葫蘆娃演示類的繼承 """ class Wa1(object): name = '紅娃' def f1(self): print('力大無窮!') class Wa2(object): name = '橙娃' def f2(self): print('千里眼順風耳') class Wa3(object): name = '黃娃' def f3(self): print('鋼筋鐵骨!') class Wa4(object): name = '綠娃' def f4(self): print('噴火!') class Wa5(object): name = '青娃' def f5(self): print('噴水!') class CYM(Wa1, Wa3, Wa5): name = '奇數娃' def ff(self): print('我叫{},我會'.format(self.name)) self.f1() self.f3() self.f5() class DBG(Wa2, Wa4): name = '偶數娃' def ff(self): print('我叫{},我會'.format(self.name)) self.f2() self.f4() # a = CYM() # a.ff() # # b = DBG() # b.ff() # class NaNa(Wa1, Wa2, Wa3, Wa4, Wa5): # name = '套娃' # # def fff(self): # print('我叫{},我會'.format(self.name)) # self.f1() # self.f2() # self.f3() # self.f4() # self.f5() # # c = NaNa() # c.fff() class SHE(CYM, DBG): name = '銀白色的娃' def fff(self): print("我叫{},我會".format(self.name)) self.f1() self.f2() self.f3() self.f4() self.f5() d = SHE() d.fff()
奇數娃,它繼承了一娃,三娃,五娃的技能django
偶數娃,它繼承了二娃,四娃的技能
套娃,它繼承了奇數娃,偶數娃的技能。也就是說,它擁有5個娃的技能
實例化3個角色,分別調用奇數娃,偶數娃,套娃的info方法
完整代碼以下:
""" 葫蘆娃演示類的繼承 """ class Wa1(object): name = '紅娃' def f1(self): print('力大無窮!') class Wa2(object): name = '橙娃' def f2(self): print('千里眼順風耳') class Wa3(object): name = '黃娃' def f3(self): print('鋼筋鐵骨!') class Wa4(object): name = '綠娃' def f4(self): print('噴火!') class Wa5(object): name = '青娃' def f5(self): print('噴水!') class Jishuwa(Wa1,Wa3,Wa5): name = '奇數娃' def info(self): print("我是%s,我會:"%self.name) self.skill() def skill(self): #技能 self.f1() self.f3() self.f5() class Oushuwa(Wa2,Wa4): name = '偶數娃' def info(self): print("我是%s,我會:" % self.name) self.skill() def skill(self): #技能 self.f2() self.f4() class Taowa(Jishuwa,Oushuwa): name = '套娃' def info(self): print("我是{},我會:".format(self.name)) self.skill() def skill(self): #技能 Jishuwa.skill(self) Oushuwa.skill(self) print('奇數娃'.center(20,'*')) role1 = Jishuwa() role1.info() print('偶數娃'.center(20,'*')) role2 = Oushuwa() role2.info() print('套娃'.center(20,'*')) role3 = Taowa() role3.info()
執行輸出:
從結果上來看,可套娃是最牛B的!
經過這個例子,慢慢來引伸下面的內容。
修改app01(應用名)目錄下的app01_serializers.py,完整代碼以下:
from app01 import models from rest_framework import serializers # 序列化評論的類 class CommentSerializer(serializers.ModelSerializer): class Meta: model = models.Comment # Comment表 fields = "__all__" # 序列化全部字段 # 定義額外的參數 extra_kwargs = { "content": { "error_messages": { "required": '內容不能爲空', } }, "article": { "error_messages": { "required": '文章不能爲空' } } } # 學校的序列化 class SchoolSerializer(serializers.ModelSerializer): class Meta: model = models.School # School表 fields = "__all__"
urls.py代碼以下:
1 from django.conf.urls import url,include 2 from django.contrib import admin 3 from app01 import app01_urls 4 5 urlpatterns = [ 6 url(r'^admin/', admin.site.urls), 7 url(r'api/', include(app01_urls)), 8 ]
app01_urls.py代碼以下:
from django.conf.urls import url from app01 import views urlpatterns = [ # 學校 url(r'school/$', views.SchoolView.as_view()), url(r'school/(?P<pk>\d+)/$', views.SchoolDetail.as_view()), ]
修改views.py,完整代碼以下:
1 from django.shortcuts import render, HttpResponse 2 from app01 import models 3 from rest_framework.views import APIView 4 from app01 import app01_serializers # 導入自定義的序列化 5 from rest_framework.response import Response 6 7 8 # Create your views here. 9 10 class SchoolView(APIView): # 全部記錄 11 def get(self, request, *args, **kwargs): # GET請求 12 queryset = models.School.objects.all() 13 # 使用自定義序列化類。當返回結果不止一條時,要指定many=True參數 14 serializers_class = app01_serializers.SchoolSerializer(queryset, many=True) 15 return Response(serializers_class.data) 16 17 18 class SchoolDetail(APIView): # 單條記錄 19 def get(self, request, pk, *args, **kwargs): 20 queryset = models.School.objects.filter(pk=pk).first() 21 serializers_class = app01_serializers.SchoolSerializer(queryset) 22 return Response(serializers_class.data)
瀏覽器訪問url: http://127.0.0.1:8000/api/comment/
效果以下:
訪問詳情:http://127.0.0.1:8000/api/school/1/
這個時候,須要增長評論表,它也須要上面2個功能:展現全部記錄和單條記錄
將2個視圖函數的代碼複製一遍,修改表名和序列化類名
from django.shortcuts import render, HttpResponse
from app01 import models
from rest_framework.views import APIView
from app01 import app01_serializers # 導入自定義的序列化
from rest_framework.response import Response
# Create your views here.
class SchoolView(APIView): # 全部記錄
def get(self, request, *args, **kwargs): # GET請求
queryset = models.School.objects.all()
# 使用自定義序列化類。當返回結果不止一條時,要指定many=True參數
serializers_class = app01_serializers.SchoolSerializer(queryset, many=True)
return Response(serializers_class.data)
class SchoolDetail(APIView): # 單條記錄
def get(self, request, pk, *args, **kwargs):
queryset = models.School.objects.filter(pk=pk).first()
serializers_class = app01_serializers.SchoolSerializer(queryset)
return Response(serializers_class.data)
class CommentView(APIView): # 全部記錄
def get(self, request, *args, **kwargs): # GET請求
queryset = models.Comment.objects.all()
# 使用自定義序列化類。當返回結果不止一條時,要指定many=True參數
serializers_class = app01_serializers.CommentSerializer(queryset, many=True)
return Response(serializers_class.data)
class CommentDetail(APIView): # 單條記錄
def get(self, request, pk, *args, **kwargs):
queryset = models.Comment.objects.filter(pk=pk).first()
serializers_class = app01_serializers.CommentSerializer(queryset)
return Response(serializers_class.data)
from django.shortcuts import render, HttpResponse from app01 import models from rest_framework.views import APIView from app01 import app01_serializers # 導入自定義的序列化 from rest_framework.response import Response # Create your views here. class SchoolView(APIView): # 全部記錄 def get(self, request, *args, **kwargs): # GET請求 queryset = models.School.objects.all() # 使用自定義序列化類。當返回結果不止一條時,要指定many=True參數 serializers_class = app01_serializers.SchoolSerializer(queryset, many=True) return Response(serializers_class.data) class SchoolDetail(APIView): # 單條記錄 def get(self, request, pk, *args, **kwargs): queryset = models.School.objects.filter(pk=pk).first() serializers_class = app01_serializers.SchoolSerializer(queryset) return Response(serializers_class.data) class CommentView(APIView): # 全部記錄 def get(self, request, *args, **kwargs): # GET請求 queryset = models.Comment.objects.all() # 使用自定義序列化類。當返回結果不止一條時,要指定many=True參數 serializers_class = app01_serializers.CommentSerializer(queryset, many=True) return Response(serializers_class.data) class CommentDetail(APIView): # 單條記錄 def get(self, request, pk, *args, **kwargs): queryset = models.Comment.objects.filter(pk=pk).first() serializers_class = app01_serializers.CommentSerializer(queryset) return Response(serializers_class.data)
修改app01_urls.py,增長2個路徑
from django.conf.urls import url
from app01 import views
urlpatterns = [
# 學校
url(r'school/$', views.SchoolView.as_view()),
url(r'school/(?P<pk>\d+)/$', views.SchoolDetail.as_view()),
# 評論
url(r'comment/$', views.CommentView.as_view()),
url(r'comment/(?P<pk>\d+)/$', views.CommentDetail.as_view()),
]
from django.conf.urls import url from app01 import views urlpatterns = [ # 學校 url(r'school/$', views.SchoolView.as_view()), url(r'school/(?P<pk>\d+)/$', views.SchoolDetail.as_view()), # 評論 url(r'comment/$', views.CommentView.as_view()), url(r'comment/(?P<pk>\d+)/$', views.CommentDetail.as_view()), ]
訪問全部評論url: http://127.0.0.1:8000/api/comment/
訪問單條評論url: http://127.0.0.1:8000/api/comment/1/
那麼問題來了,再來一個表呢?再複製2個視圖函數,修改表名和序列化類名?
這不符合編程習慣,得須要將相同的代碼,封裝成一個類。那麼其餘表就能夠繼承了!
那麼接下來的GenericAPIView就展現了它強大的功能
GenericAPIView對APIView再次封裝,實現了強大功能:
GenericAPIView的五個擴展類給咱們提供了五個方法分別進行增刪改查的不一樣操做,這樣咱們就不用寫那麼多函數
五個擴展類(爲啥是5個?答:增刪改查,查有兩個)
搭配GenericAPIView使用
1.ListModelMixin: 提供list方法快速實現列表視圖(多條數據)
2.CreateModelMixin: 提供create方法快速實現建立資源的視圖
3.RetrieveModelMixin 提供retrieve方法,能夠快速實現返回一個存在的數據對象(須要傳入pk)
4.UpdateModelMixin 提供update方法,能夠快速實現更新一個存在的數據對象。 提供partial_update方法,能夠實現局部更新
5.DestroyModelMixin 提供destroy方法,能夠快速實現刪除一個存在的數據對象
注意:GenericAPIView不能單獨使用,它須要和上面的5個擴展類配合使用才行
源碼分析,請參考文章:
https://blog.csdn.net/u013210620/article/details/79869661
它返回數據列表,也就是多條數據
使用時,須要導入模塊
from rest_framework.mixins import ListModelMixin
它負責單條數據的獲取、更新、刪除
使用時,須要導入模塊
from rest_framework.mixins import RetrieveModelMixin
舉例:將上面4個視圖函數改爲GenericAPIView+ListModelMixin+RetrieveModelMixin
使用前,須要導入模塊
from rest_framework.generics import GenericAPIView from rest_framework.mixins import ListModelMixin
GenericAPIView只須要配置queryset和serializer_class
修改views.py,完整代碼以下:
from django.shortcuts import render,HttpResponse from app01 import models from rest_framework.views import APIView from app01 import app01_serialization #導入自定義的序列化 from rest_framework.response import Response from rest_framework.generics import GenericAPIView from rest_framework.mixins import ListModelMixin,RetrieveModelMixin class SchoolView(GenericAPIView,ListModelMixin): queryset = models.School.objects.all() serializer_class = app01_serialization.SchoolSerializer def get(self,request,*args,**kwargs): #GET請求 return self.list(request,*args,**kwargs) #RetrieveModelMixin 表示查詢單條數據,須要傳入pk參數 class SchoolDetail(GenericAPIView,RetrieveModelMixin): queryset = models.School.objects.all() serializer_class = app01_serialization.SchoolSerializer def get(self,request,pk,*args,**kwargs): #GET請求 return self.retrieve(request,pk,*args,**kwargs) class CommentView(GenericAPIView,ListModelMixin): queryset = models.Comment.objects.all() serializer_class = app01_serialization.CommentSerializer def get(self,request,*args,**kwargs): return self.list(request,*args,**kwargs) class CommentDetail(GenericAPIView,RetrieveModelMixin): queryset = models.Comment.objects.all() serializer_class = app01_serialization.CommentSerializer def get(self,request,pk,*args,**kwargs): return self.retrieve(request,pk,*args,**kwargs)
訪問不一樣的url,效果和上面是同樣的!
http://127.0.0.1:8000/api/comment/
http://127.0.0.1:8000/api/comment/1/
http://127.0.0.1:8000/api/school/
http://127.0.0.1:8000/api/school/1/
JsonResponse和Response的區別
JsonResponse和Response均可以返回json對象。不一樣之處在於:
使用Response時,若是是瀏覽器訪問,就會返回一個頁面,效果就是上面的圖片。
可是使用postman工具時,返回json數據,並不會有頁面。
而JsonResponse則沒有這個功能,始終都是json對象
它負責增長一條記錄
使用時,須要導入模塊
from rest_framework.mixins import CreateModelMixin
舉例:增長一條評論
修改views.py,完整代碼以下:
1 from django.shortcuts import render, HttpResponse 2 from app01 import models 3 from rest_framework.views import APIView 4 from app01 import app01_serializers # 導入自定義的序列化 5 from rest_framework.response import Response 6 from rest_framework.generics import GenericAPIView 7 from rest_framework.mixins import ListModelMixin, RetrieveModelMixin,CreateModelMixin 8 9 10 # Create your views here. 11 12 class SchoolView(GenericAPIView, ListModelMixin): 13 queryset = models.School.objects.all() 14 serializer_class = app01_serializers.SchoolSerializer 15 16 def get(self, request, *args, **kwargs): # GET請求 17 return self.list(request, *args, **kwargs) 18 19 20 # RetrieveModelMixin 表示查詢單條數據,須要傳入pk參數 21 class SchoolDetail(GenericAPIView, RetrieveModelMixin): 22 queryset = models.School.objects.all() 23 serializer_class = app01_serializers.SchoolSerializer 24 25 def get(self, request, pk, *args, **kwargs): # GET請求 26 return self.retrieve(request, pk, *args, **kwargs) 27 28 29 class CommentView(GenericAPIView, ListModelMixin,CreateModelMixin): 30 queryset = models.Comment.objects.all() 31 serializer_class = app01_serializers.CommentSerializer 32 33 def get(self, request, *args, **kwargs): # GET請求 34 return self.list(request, *args, **kwargs) 35 36 def post(self, request, *args, **kwargs): # POST請求 37 return self.create(request, *args, **kwargs) 38 39 40 # RetrieveModelMixin 表示查詢單條數據,須要傳入pk參數 41 class CommentDetail(GenericAPIView, RetrieveModelMixin): 42 queryset = models.Comment.objects.all() 43 serializer_class = app01_serializers.CommentSerializer 44 45 def get(self, request, pk, *args, **kwargs): # GET請求 46 return self.retrieve(request, pk, *args, **kwargs)
json數據
{ "content": "噗嗤", "article": 2 }
指定格式爲JSON
查看返回結果,它會增長的數據
查看app01_comment表
刪除單條數據
使用時,須要導入模塊
from rest_framework.mixins import DestroyModelMixin
舉例:刪除一條評論,那麼在刪除以前,能夠打印一句話
1 from django.shortcuts import render, HttpResponse 2 from app01 import models 3 from rest_framework.views import APIView 4 from app01 import app01_serializers # 導入自定義的序列化 5 from rest_framework.response import Response 6 from rest_framework.generics import GenericAPIView 7 from rest_framework.mixins import ListModelMixin, RetrieveModelMixin 8 from rest_framework.mixins import CreateModelMixin, DestroyModelMixin 9 10 # Create your views here. 11 12 class SchoolView(GenericAPIView, ListModelMixin): 13 queryset = models.School.objects.all() 14 serializer_class = app01_serializers.SchoolSerializer 15 16 def get(self, request, *args, **kwargs): # GET請求 17 return self.list(request, *args, **kwargs) 18 19 20 # RetrieveModelMixin 表示查詢單條數據,須要傳入pk參數 21 class SchoolDetail(GenericAPIView, RetrieveModelMixin): 22 queryset = models.School.objects.all() 23 serializer_class = app01_serializers.SchoolSerializer 24 25 def get(self, request, pk, *args, **kwargs): # GET請求 26 return self.retrieve(request, pk, *args, **kwargs) 27 28 29 class CommentView(GenericAPIView, ListModelMixin,CreateModelMixin): 30 queryset = models.Comment.objects.all() 31 serializer_class = app01_serializers.CommentSerializer 32 33 def get(self, request, *args, **kwargs): # GET請求 34 return self.list(request, *args, **kwargs) 35 36 def post(self, request, *args, **kwargs): # POST請求 37 return self.create(request, *args, **kwargs) 38 39 40 # RetrieveModelMixin 表示查詢單條數據,須要傳入pk參數 41 class CommentDetail(GenericAPIView, RetrieveModelMixin,DestroyModelMixin): 42 queryset = models.Comment.objects.all() 43 serializer_class = app01_serializers.CommentSerializer 44 45 def get(self, request, pk, *args, **kwargs): # GET請求 46 return self.retrieve(request, pk, *args, **kwargs) 47 48 def delete(self, request, pk, *args, **kwargs): # DELETE請求 49 return self.destroy(request, pk, *args, **kwargs) 50 51 def perform_destroy(self, instance): 52 print("你真的真的肯定要刪除了嗎?...") 53 instance.delete()
使用postman發送delete請求,注意:數字後面必定要有 / ,不然不沒有效果
由於路由規則定義,必須以 / 結尾!
它的返回結果爲空
查看Pycharm控制檯輸出:
你真的真的肯定要刪除了嗎?...
更新單條數據
使用時,須要導入模塊
from rest_framework.mixins import UpdateModelMixin
舉例:更新一條評論
舉例:更新一條評論
from django.shortcuts import render, HttpResponse
from app01 import models
from rest_framework.views import APIView
from app01 import app01_serializers # 導入自定義的序列化
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin,UpdateModelMixin
# Create your views here.
class SchoolView(GenericAPIView, ListModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer
def get(self, request, *args, **kwargs): # GET請求
return self.list(request, *args, **kwargs)
# RetrieveModelMixin 表示查詢單條數據,須要傳入pk參數
class SchoolDetail(GenericAPIView, RetrieveModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer
def get(self, request, pk, *args, **kwargs): # GET請求
return self.retrieve(request, pk, *args, **kwargs)
class CommentView(GenericAPIView, ListModelMixin,CreateModelMixin):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer
def get(self, request, *args, **kwargs): # GET請求
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs): # POST請求
return self.create(request, *args, **kwargs)
# RetrieveModelMixin 表示查詢單條數據,須要傳入pk參數
class CommentDetail(GenericAPIView, RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer
def get(self, request, pk, *args, **kwargs): # GET請求
return self.retrieve(request, pk, *args, **kwargs)
def delete(self, request, pk, *args, **kwargs): # DELETE請求
return self.destroy(request, pk, *args, **kwargs)
def perform_destroy(self, instance):
print("你真的真的肯定要刪除了嗎?...")
instance.delete()
def put(self, request, pk, *args, **kwargs): # PUT請求
return self.update(request, pk, *args, **kwargs)
from django.shortcuts import render, HttpResponse from app01 import models from rest_framework.views import APIView from app01 import app01_serializers # 導入自定義的序列化 from rest_framework.response import Response from rest_framework.generics import GenericAPIView from rest_framework.mixins import ListModelMixin, RetrieveModelMixin from rest_framework.mixins import CreateModelMixin, DestroyModelMixin,UpdateModelMixin # Create your views here. class SchoolView(GenericAPIView, ListModelMixin): queryset = models.School.objects.all() serializer_class = app01_serializers.SchoolSerializer def get(self, request, *args, **kwargs): # GET請求 return self.list(request, *args, **kwargs) # RetrieveModelMixin 表示查詢單條數據,須要傳入pk參數 class SchoolDetail(GenericAPIView, RetrieveModelMixin): queryset = models.School.objects.all() serializer_class = app01_serializers.SchoolSerializer def get(self, request, pk, *args, **kwargs): # GET請求 return self.retrieve(request, pk, *args, **kwargs) class CommentView(GenericAPIView, ListModelMixin,CreateModelMixin): queryset = models.Comment.objects.all() serializer_class = app01_serializers.CommentSerializer def get(self, request, *args, **kwargs): # GET請求 return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): # POST請求 return self.create(request, *args, **kwargs) # RetrieveModelMixin 表示查詢單條數據,須要傳入pk參數 class CommentDetail(GenericAPIView, RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin): queryset = models.Comment.objects.all() serializer_class = app01_serializers.CommentSerializer def get(self, request, pk, *args, **kwargs): # GET請求 return self.retrieve(request, pk, *args, **kwargs) def delete(self, request, pk, *args, **kwargs): # DELETE請求 return self.destroy(request, pk, *args, **kwargs) def perform_destroy(self, instance): print("你真的真的肯定要刪除了嗎?...") instance.delete() def put(self, request, pk, *args, **kwargs): # PUT請求 return self.update(request, pk, *args, **kwargs)
json數據
{ "id": 6, "content": "從前的日色變得慢", "article": 1 }
使用put發送,選擇JSON
若是返回結果是:
415(Unsupported Media Type)不支持的類型異常
請查看Headers,必定要勾選
再次發送,查看返回結果
查看錶app01_comment,發現記錄更新了!
Django REST framework提供了9個通用視圖,詳情請參考如下連接中的《混凝土視圖類》
https://www.cnblogs.com/yangxiaoling/p/6914880.html
用於讀寫刪除端點來表示單個模型實例。
提供get
,put
,patch
和delete
方法處理。
擴展:GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
它至關於上面葫蘆娃例子中的奇數娃
使用須要導入模塊
from rest_framework.generics import RetrieveUpdateDestroyAPIView
舉例:將CommentDetail改形成RetrieveUpdateDestroyAPIView
它擁有get,put,patch和delete方法處理,因此以前的那些方法,均可以幹掉了!
測試GET
測試POST,注意後面沒有數字
查看返回結果
查看錶app01_comment,發現多了一條記錄
ModelViewSet視圖集會自動提供list,create, retrieve, update & destroy這些行爲,
查看源代碼:它有6個功能
也就說它具備5個葫蘆娃的能力,也就是上面面向對象講到的套娃
使用時,須要導入模塊
from rest_framework.viewsets import ModelViewSet
處理器方法只有在定義了URLConf的時候纔會綁定這些行爲。
在urls.py文件中,咱們把ViewSet綁定到一些具體的視圖上
修改app01_urls.py
from django.conf.urls import url from app01 import views urlpatterns = [ # 學校 url(r'school/$', views.SchoolView.as_view()), url(r'school/(?P<pk>\d+)/$', views.SchoolDetail.as_view()), # 評論 url(r'comment/$', views.CommentViewSet.as_view({ 'get': "list", 'post': 'create' })), url(r'comment/(?P<pk>\d+)/$', views.CommentViewSet.as_view({ 'get': 'retrieve', 'put': 'update', 'delete': 'destroy' })), ]
參數解釋:
get, post , put , delete分別表示不一樣的請求方式
後面對應的值分別是ListModelMixin,
CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
修改views.py,增長一個視圖函數,註釋多餘的代碼
from django.shortcuts import render, HttpResponse from app01 import models from rest_framework.views import APIView from app01 import app01_serializers # 導入自定義的序列化 from rest_framework.response import Response from rest_framework.generics import GenericAPIView,RetrieveUpdateDestroyAPIView,ListCreateAPIView from rest_framework.mixins import ListModelMixin, RetrieveModelMixin from rest_framework.mixins import CreateModelMixin, DestroyModelMixin,UpdateModelMixin from rest_framework.viewsets import ModelViewSet # Create your views here. class SchoolView(GenericAPIView, ListModelMixin): queryset = models.School.objects.all() serializer_class = app01_serializers.SchoolSerializer def get(self, request, *args, **kwargs): # GET請求 return self.list(request, *args, **kwargs) # RetrieveModelMixin 表示查詢單條數據,須要傳入pk參數 class SchoolDetail(GenericAPIView, RetrieveModelMixin): queryset = models.School.objects.all() serializer_class = app01_serializers.SchoolSerializer def get(self, request, pk, *args, **kwargs): # GET請求 return self.retrieve(request, pk, *args, **kwargs) # class CommentView(ListCreateAPIView): # queryset = models.Comment.objects.all() # serializer_class = app01_serializers.CommentSerializer # # # class CommentDetail(RetrieveUpdateDestroyAPIView): # queryset = models.Comment.objects.all() # serializer_class = app01_serializers.CommentSerializer class CommentViewSet(ModelViewSet): queryset = models.Comment.objects.all() serializer_class = app01_serializers.CommentSerializer
一個視圖函數,就搞定了5種請求方式,驚歎不已!
測試GET
後面的幾種請求方式,你們能夠自行測試!
同上,仍是使用ModelViewSet
由於咱們正在使用ViewSet
代替View
,實際上已經再也不須要本身來設計URL的配置了。將資源和視圖、URL綁定到一塊兒是一個能夠自動完成的過程,只須要使用Router
便可。咱們須要作的就是將視圖集註冊到Router上去而已。
修改app01_urls.py
from django.conf.urls import url from app01 import views urlpatterns = [ # 學校 url(r'school/$', views.SchoolView.as_view()), url(r'school/(?P<pk>\d+)/$', views.SchoolDetail.as_view()), # 評論 # url(r'comment/$', views.CommentViewSet.as_view({ # 'get': "list", # 'post': 'create' # })), # # url(r'comment/(?P<pk>\d+)/$', views.CommentViewSet.as_view({ # 'get': 'retrieve', # 'put': 'update', # 'delete': 'destroy' # })), ] from rest_framework.routers import DefaultRouter router = DefaultRouter() # 註冊路由,表示路徑comment對應視圖函數CommentViewSet router.register(r'comment', views.CommentViewSet) urlpatterns += router.urls
將ViewSets 註冊到Router的過程實際上相似於提供一個urlpattern。咱們引入了兩個參數,一個是views的URL prefix,另外一個是viewset自己。
咱們使用DefaultRouter 也會自動的幫咱們建立API root視圖,多餘路由能夠註銷掉了。
作開發開不開日誌,如下是我在工做中寫Django項目經常使用的logging配置。
修改settings.py,最後一行添加
# 日誌相關配置 LOGGING = { 'version': 1, # 保留字段 'disable_existing_loggers': False, # 不要禁用已經存在的logger實例 'formatters': { # 定義三種日誌顯示的格式 'standard': { 'format': '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' '[%(levelname)s][%(message)s]' }, 'simple': { 'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' }, 'collect': { 'format': '%(message)s' } }, 'filters': { # 定義一個過濾規則 'require_debug_true': { '()': 'django.utils.log.RequireDebugTrue', }, }, 'handlers': { # 日誌流的處理方式 'console': { # 把日誌打印到終端 'level': 'DEBUG', 'filters': ['require_debug_true'], # 只有在Django debug爲True時纔在屏幕打印日誌 'class': 'logging.StreamHandler', 'formatter': 'simple' }, 'default': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自動切 'filename': os.path.join(BASE_LOG_DIR, "info.log"), # 日誌文件 'maxBytes': 1024 * 1024 * 500, # 日誌大小 500M 'backupCount': 3, # 'formatter': 'standard', 'encoding': 'utf-8', }, 'error': { 'level': 'ERROR', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自動切 'filename': os.path.join(BASE_LOG_DIR, "err.log"), # 日誌文件 'maxBytes': 1024 * 1024 * 500, # 日誌大小 500M 'backupCount': 5, 'formatter': 'standard', 'encoding': 'utf-8', }, 'collect': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自動切 'filename': os.path.join(BASE_LOG_DIR, "collect.log"), 'maxBytes': 1024 * 1024 * 500, # 日誌大小 500M 'backupCount': 5, 'formatter': 'collect', 'encoding': "utf-8" } }, 'loggers': { # 默認的logger應用以下配置 '': { 'handlers': ['default', 'console', 'error'], # 上線以後能夠把'console'移除 'level': 'DEBUG', 'propagate': True, # 是否向父級logger實例傳遞日誌信息 }, # 名爲 'collect'的logger還單獨處理 'collect': { 'handlers': ['console', 'collect'], 'level': 'INFO', } }, }
在視圖函數中使用時,先導入模塊,並聲明變量
import logging # 生成一個以當前文件名爲名字的 logger實例 logger = logging.getLogger(__name__) # 生成一個名字爲collect的日誌實例 collect_logger = logging.getLogger('collect')
而後在邏輯代碼中加入
logger.warning('找不到記錄...') 或者 collect_logger.info(name)
附:Python logger流示圖
django-debug-toolbar 是一組可配置的面板,可顯示有關當前請求/響應的各類調試信息,並在單擊時顯示有關面板內容的更多詳細信息。
pip3 install django-debug-toolbar
將 debug_toolbar 添加到 INSTALL_APPS 中,最後一行添加
INSTALLED_APPS = [ … 'debug_toolbar', ]
1 from django.conf import settings 2 from django.conf.urls import include, url 3 4 if settings.DEBUG: 5 import debug_toolbar 6 urlpatterns = [ 7 url(r'^__debug__/', include(debug_toolbar.urls)), 8 ] + urlpatterns
在中間件中加入DebugToolbarMiddleware,最後一行添加
MIDDLEWARE = [ # ... 'debug_toolbar.middleware.DebugToolbarMiddleware', ]
若是是本機調試,還在將127.0.0.1加入 INTERNAL_IPS
在settings.py中加入如下配置項:
INTERNAL_IPS = ['127.0.0.1', ]
5. 配置jQuery的URL
django-debug-toolbar 默認使用的是Google的地址,默認配置以下:
JQUERY_URL = '//ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js'
國內用不了的話能夠在settings.py中配置一下,例如(我這裏特地選用了和原做者相同版本的jQuery):
修改settings.py,最後一行添加
DEBUG_TOOLBAR_CONFIG = { "JQUERY_URL": '//cdn.bootcss.com/jquery/2.2.4/jquery.min.js', }
或者你若是在Django項目中使用了jquery的話就能夠直接將這一項置爲空,那麼django-debug-toolbar 就會使用你項目中用到的jquery:
DEBUG_TOOLBAR_CONFIG = { "JQUERY_URL": '', }
訪問具體路徑的時候在頁面右側有各項配置面板,點擊便可查看各類調試信息。