DRF中的Request


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__"
Views

路由

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 ]
urls.py 代碼

 

 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)
Views.py

瀏覽器訪問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

GenericAPIView對APIView再次封裝,實現了強大功能:

  •   加入queryset屬性,能夠直接設置這個屬性,沒必要再將實例的courses,再次傳給seriliazer,系統會自動檢測到。除此以外,能夠重載get_queryset(),這樣就沒必要設置‘queryset=* ’,這樣就變得更加靈活,能夠進行徹底的自定義。
  • 加入serializer_class屬性與實現get_serializer_class()方法。二者的存在一個便可,經過這個,在返回時,沒必要去指定某個serilizer
  • 設置過濾模版:filter_backends
  • 設置分頁模版:pagination_class
  • 加入lookup_field="pk",以及實現了get_object方法:這個用得場景很少,但十分重要。他們二者的關係同理,要麼設置屬性,要麼重載方法。他們的功能在於獲取某一個實例時,指定傳進來的後綴是什麼。

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

 

ListModelMixin

它返回數據列表,也就是多條數據

使用時,須要導入模塊

from rest_framework.mixins import ListModelMixin

 

RetrieveModelMixin 

它負責單條數據的獲取、更新、刪除

使用時,須要導入模塊

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對象

 

CreateModelMixin

它負責增長一條記錄

使用時,須要導入模塊

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)
Views.py

json數據

{
    "content": "噗嗤",
    "article": 2
}

指定格式爲JSON

查看返回結果,它會增長的數據

查看app01_comment表

 

DestroyModelMixin

 刪除單條數據

使用時,須要導入模塊

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()
Views.py

使用postman發送delete請求,注意:數字後面必定要有 / ,不然不沒有效果

由於路由規則定義,必須以 / 結尾!

它的返回結果爲空

查看Pycharm控制檯輸出:

你真的真的肯定要刪除了嗎?...

UpdateModelMixin

更新單條數據

使用時,須要導入模塊

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

 

RetrieveUpdateDestroyAPIView

用於讀寫刪除端點來表示單個模型實例

提供getputpatchdelete方法處理。

擴展:GenericAPIViewRetrieveModelMixinUpdateModelMixinDestroyModelMixin

 

它至關於上面葫蘆娃例子中的奇數娃

使用須要導入模塊

from rest_framework.generics import RetrieveUpdateDestroyAPIView

舉例:將CommentDetail改形成RetrieveUpdateDestroyAPIView

它擁有get,put,patch和delete方法處理,因此以前的那些方法,均可以幹掉了!

 

測試GET

測試POST,注意後面沒有數字

查看返回結果

查看錶app01_comment,發現多了一條記錄

 

牛牛牛牛之使用視圖集

ModelViewSet

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視圖,多餘路由能夠註銷掉了。

贈圖一張,祝君好運

2、django logging配置

作開發開不開日誌,如下是我在工做中寫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流示圖

附:Python logger流示圖

 

3、django-debug-toolbar使用指南

介紹

django-debug-toolbar 是一組可配置的面板,可顯示有關當前請求/響應的各類調試信息,並在單擊時顯示有關面板內容的更多詳細信息。

github地址

文檔地址

安裝

pip3 install django-debug-toolbar

配置

1. settings.py中

將 debug_toolbar 添加到 INSTALL_APPS 中,最後一行添加

INSTALLED_APPS = [
    …
    'debug_toolbar',
]

2. urls.py中

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
urls.py

3. settings.py中

在中間件中加入DebugToolbarMiddleware,最後一行添加

MIDDLEWARE = [
    # ...
    'debug_toolbar.middleware.DebugToolbarMiddleware',
]

4.加入 INTERNAL_IPS

若是是本機調試,還在將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": '',
}

使用

訪問具體路徑的時候在頁面右側有各項配置面板,點擊便可查看各類調試信息。

相關文章
相關標籤/搜索