01-django-rest-framework

參考博客

[置頂]Python系列教程 | Justin-劉清政的博客

app01/ser.py代碼

from django.db import models

# Create your models here.
class Book(models.Model):
    id=models.AutoField(primary_key=True)
    name=models.CharField(max_length=32)
    price=models.DecimalField(max_digits=5,decimal_places=2)
    author=models.CharField(max_length=32)
    publish=models.CharField(max_length=32)
# from rest_framework.serializers import Serializer  # 就是一個(gè)類
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
# 需要繼承 Serializer
from app01.models import Book

def check_author(data):
    if data.startswith('sb'):
        raise ValidationError('作者名字不能以sb開頭')
    else:
        return data


class BookSerializer(serializers.Serializer):
    id=serializers.CharField(read_only=True)
    name=serializers.CharField(max_length=16,min_length=4)
    # price=serializers.DecimalField()
    price=serializers.CharField(write_only=True,required=True)
    author=serializers.CharField(validators=[check_author])  # validators=[] 列表中寫函數(shù)內(nèi)存地址
    publish=serializers.CharField()

    def validate_price(self, data):   # validate_字段名  接收一個(gè)參數(shù)
        #如果價(jià)格小于10,就校驗(yàn)不通過
        # print(type(data))
        # print(data)
        if float(data)>10:
            return data
        else:
            #校驗(yàn)失敗,拋異常
            raise ValidationError('價(jià)格太低')
    def validate(self, validate_data):   # 全局鉤子
        print(validate_data)
        author=validate_data.get('author')
        publish=validate_data.get('publish')
        if author == publish:
            raise ValidationError('作者名字跟出版社一樣')
        else:
            return validate_data
    def update(self, instance, validated_data):
        #instance是book這個(gè)對象
        #validated_data是校驗(yàn)后的數(shù)據(jù)
        instance.name=validated_data.get('name')
        instance.price=validated_data.get('price')
        instance.author=validated_data.get('author')
        instance.publish=validated_data.get('publish')
        instance.save()  #book.save()   django 的orm提供的
        return instance
    def create(self, validated_data):
        instance=Book.objects.create(**validated_data)
        return instance
        # Book.objects.create(name=validated_data.get('name'))


class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model=Book  # 對應(yīng)上models.py中的模型
        fields='__all__'
        # fields=('name','price','id','author') # 只序列化指定的字段
        # exclude=('name',) #跟fields不能都寫,寫誰,就表示排除誰
        # read_only_fields=('price',)
        # write_only_fields=('id',) #棄用了,使用extra_kwargs
        extra_kwargs = {  # 類似于這種形式name=serializers.CharField(max_length=16,min_length=4)
            'price': {'write_only': True},
        }

app01/views.py

from django.shortcuts import render

# Create your views here.
from django.http import JsonResponse

from rest_framework.views import APIView
from app01.models import Book
from app01.ser import BookSerializer
from app01.ser import BookModelSerializer
from rest_framework.response import Response  #drf 提供的響應(yīng)對象

# 導(dǎo)入自己寫的response類
from app01.utils import MyResponse
class BookView(APIView):
    def get(self,request,pk):
        book=Book.objects.filter(id=pk).first()
        #用一個(gè)類,毫無疑問,一定要實(shí)例化
        #要序列化誰,就把誰傳過來
        book_ser=BookSerializer(book)  # 調(diào)用類的__init__
        # book_ser.data   序列化對象.data就是序列化后的字典
        return Response(book_ser.data)
        # return JsonResponse(book_ser.data)

    def put(self,request,pk):
        response_msg={'status':100,'msg':'成功'}
        # 找到這個(gè)對象
        book = Book.objects.filter(id=pk).first()
        # 得到一個(gè)序列化類的對象
        # boo_ser=BookSerializer(book,request.data)
        boo_ser=BookSerializer(instance=book,data=request.data)

        # 要數(shù)據(jù)驗(yàn)證(回想form表單的驗(yàn)證)
        if boo_ser.is_valid():  # 返回True表示驗(yàn)證通過
            boo_ser.save()  # 報(bào)錯(cuò)
            response_msg['data']=boo_ser.data
        else:
            response_msg['status']=101
            response_msg['msg']='數(shù)據(jù)校驗(yàn)失敗'
            response_msg['data']=boo_ser.errors

        return Response(response_msg)

    def delete(self,request,pk):
        response=MyResponse()
        ret=Book.objects.filter(pk=pk).delete()
        return Response(response.get_dict)

class BooksView(APIView):
    # def get(self,request):
    #     response_msg = {'status': 100, 'msg': '成功'}
    #     books=Book.objects.all()
    #     book_ser=BookSerializer(books,many=True)  #序列化多條,如果序列化一條,不需要寫
    #     response_msg['data']=book_ser.data
    #     return Response(response_msg)

    def get(self,request):
        response=MyResponse()
        books=Book.objects.all()
        book_ser=BookSerializer(books,many=True)  #序列化多條,如果序列化一條,不需要寫
        response.data=book_ser.data
        return Response(response.get_dict)

    # 新增
    def post(self,request):
        response_msg = {'status': 100, 'msg': '成功'}
        #修改才有instance,新增沒有instance,只有data
        book_ser = BookSerializer(data=request.data)
        # book_ser = BookSerializer(request.data)  # 這個(gè)按位置傳request.data會(huì)給instance,就報(bào)錯(cuò)了
        # 校驗(yàn)字段
        if book_ser.is_valid():
            book_ser.save()
            response_msg['data']=book_ser.data
        else:
            response_msg['status']=102
            response_msg['msg']='數(shù)據(jù)校驗(yàn)失敗'
            response_msg['data']=book_ser.errors
        return Response(response_msg)


class BooksView2(APIView):
    def get(self,request):
        response=MyResponse()
        books=Book.objects.all()
        book=Book.objects.all().first()
        book_ser=BookModelSerializer(books,many=True)
        book_one_ser=BookModelSerializer(book)
        print(type(book_ser))
        print(type(book_one_ser))
        response.data=book_ser.data
        return Response(response.get_dict)


APIView源碼分析


drf的Request類


drf序列化

序列化與反序列化介紹



需要在installed_app中注冊一下'rest_framework',不然報(bào)錯(cuò),如果使用Jsonresponse返回,則可以不用注冊

序列化對象.data直接拿到j(luò)son數(shù)據(jù)
可以將rest_framework的response替換成jsonresponse,前者只是給返回的數(shù)據(jù)做了一個(gè)界面美化。

序列化字段的類型

使用charfield就返回字符串格式的json


  • 數(shù)據(jù)庫定義的字段類型和序列化類寫的字段可以不一樣,都用charfield沒問題


  • 路由


  • 序列化器
  • 需要查看哪些字段就寫哪些字段


  • 字段選擇


  • 將從數(shù)據(jù)庫取出的數(shù)據(jù)傳給序列化器,再使用response轉(zhuǎn)成json返回(使用drf帶的response需要先把rf注冊到app,否則報(bào)錯(cuò)模板不存在)


序列化字段選項(xiàng)

  • 使用接口,put,post數(shù)據(jù)時(shí)做數(shù)據(jù)校驗(yàn)



  • put方法修改數(shù)據(jù)
  • 之前的修改數(shù)據(jù)方式



  • 接口規(guī)范控制:抽象類abc、拋異常



  • 重寫update,更新數(shù)據(jù)


  • 集成的父類中有這個(gè)父類內(nèi)部調(diào)用這個(gè)方法,優(yōu)先使用重寫的這個(gè)方法


序列化組件修改數(shù)據(jù)

自定義校驗(yàn):局部鉤子、全局鉤子校驗(yàn):指定字段校驗(yàn)(類似form)

數(shù)據(jù)保存之前,可以使用鉤子校驗(yàn)規(guī)則
validate_字段名     #局部鉤子
validate # 全局鉤子

字段訪問控制

  • readonly只可以查看,不可以寫的字段
  • writeonly只可以寫,不可以查
class BookSerializer(serializers.Serializer):
    id=serializers.CharField(read_only=True)
    name=serializers.CharField(max_length=16,min_length=4)
    # price=serializers.DecimalField()
    price=serializers.CharField(write_only=True,required=True)
    author=serializers.CharField(validators=[check_author])  # validators=[] 列表中寫函數(shù)內(nèi)存地址
    publish=serializers.CharField()
  • get
  • 序列化多條加many
from app01.models import Book
from app01.ser import BookSerializer
from rest_framework.views import APIView
from rest_framework.response import Response 
class BooksView(APIView):
    def get(self,request):
        response=MyResponse()
        books=Book.objects.all()
        book_ser=BookSerializer(books,many=True)  #序列化多條,如果序列化一條,不需要寫
        response.data=book_ser.data
        return Response(response.get_dict)
  • 新增post
  • 需要修改序列化類的create方法
ser.py
# from rest_framework.serializers import Serializer  # 就是一個(gè)類
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
# 需要繼承 Serializer
from app01.models import Book
class BookSerializer(serializers.Serializer):
    id=serializers.CharField(read_only=True)
    name=serializers.CharField(max_length=16,min_length=4)
    # price=serializers.DecimalField()
    price=serializers.CharField(write_only=True,required=True)
    author=serializers.CharField(validators=[check_author])  # validators=[] 列表中寫函數(shù)內(nèi)存地址
    publish=serializers.CharField()

    def validate_price(self, data):   # validate_字段名  接收一個(gè)參數(shù)
        #如果價(jià)格小于10,就校驗(yàn)不通過
        #如果價(jià)格小于10,就校驗(yàn)不通過
        # print(type(data))
        # print(data)
        if float(data)>10:
            return data
        else:
            #校驗(yàn)失敗,拋異常
            raise ValidationError('價(jià)格太低')
    def validate(self, validate_data):   # 全局鉤子
        print(validate_data)
        author=validate_data.get('author')
        publish=validate_data.get('publish')
        if author == publish:
            raise ValidationError('作者名字跟出版社一樣')
        else:
            return validate_data
    def update(self, instance, validated_data):
        #instance是book這個(gè)對象
        #validated_data是校驗(yàn)后的數(shù)據(jù)
        instance.name=validated_data.get('name')
        instance.price=validated_data.get('price')
        instance.author=validated_data.get('author')
        instance.publish=validated_data.get('publish')
        instance.save()  #book.save()   django 的orm提供的
        return instance
    def create(self, validated_data):
        instance=Book.objects.create(**validated_data)
        return instance
        # Book.objects.create(name=validated_data.get('name'))


views.py
from app01.models import Book
from app01.ser import BookSerializer
from rest_framework.views import APIView
from rest_framework.response import Response 
    # 新增
    def post(self,request):
        response_msg = {'status': 100, 'msg': '成功'}
        #修改才有instance,新增沒有instance,只有data
        book_ser = BookSerializer(data=request.data)
        # book_ser = BookSerializer(request.data)  # 這個(gè)按位置傳request.data會(huì)給instance,就報(bào)錯(cuò)了
        # 校驗(yàn)字段
        if book_ser.is_valid():
            book_ser.save()
            response_msg['data']=book_ser.data
        else:
            response_msg['status']=102
            response_msg['msg']='數(shù)據(jù)校驗(yàn)失敗'
            response_msg['data']=book_ser.errors
        return Response(response_msg)
  • 修改put
  • 需要傳book實(shí)例
  • 需要重寫update方法
from app01.models import Book
from app01.ser import BookSerializer
from rest_framework.views import APIView
from rest_framework.response import Response 
class BookView(APIView):
    def put(self,request,pk):
        response_msg={'status':100,'msg':'成功'}
        # 找到這個(gè)對象
        book = Book.objects.filter(id=pk).first()
        # 得到一個(gè)序列化類的對象
        # boo_ser=BookSerializer(book,request.data)
        boo_ser=BookSerializer(instance=book,data=request.data)

        # 要數(shù)據(jù)驗(yàn)證(回想form表單的驗(yàn)證)
        if boo_ser.is_valid():  # 返回True表示驗(yàn)證通過
            boo_ser.save()  # 報(bào)錯(cuò)
            response_msg['data']=boo_ser.data
        else:
            response_msg['status']=101
            response_msg['msg']='數(shù)據(jù)校驗(yàn)失敗'
            response_msg['data']=boo_ser.errors

        return Response(response_msg)
  • delete刪除
  • 直接操作book對象,不需要重寫方法
from app01.models import Book
from app01.ser import BookSerializer
from rest_framework.views import APIView
from rest_framework.response import Response 
    def delete(self,request,pk):
        response=MyResponse()
        ret=Book.objects.filter(pk=pk).delete()
        return Response(response.get_dict)
  • 類封裝返回信息
app1/uitls.py
class MyResponse():
    def __init__(self):
        self.status=100
        self.msg='成功'
    @property
    def get_dict(self):
        return self.__dict__


if __name__ == '__main__':
    res=MyResponse()
    res.status=101
    res.msg='查詢失敗'
    # res.data={'name':'lqz'}
    print(res.get_dict)
  • 類封裝返回信息的使用


模型類的序列化器

  • app/views.py
from rest_framework.views import APIView
from app01.models import Book
from app01.ser import BookModelSerializer
from rest_framework.response import Response  #drf 提供的響應(yīng)對象
# 導(dǎo)入自己寫的response類
from app01.utils import MyResponse
class BooksView2(APIView):
    def get(self,request):
        response=MyResponse()
        books=Book.objects.all()
        book=Book.objects.all().first()
        book_ser=BookModelSerializer(books,many=True)
        book_one_ser=BookModelSerializer(book)
        print(type(book_ser))
        print(type(book_one_ser))
        response.data=book_ser.data
        return Response(response.get_dict)
  • app/ser.py
  • 對應(yīng)上models.py中的模型,不需重寫update和create
from rest_framework import serializers
class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model=Book  # 對應(yīng)上models.py中的模型
        fields='__all__'
        # fields=('name','price','id','author') # 只序列化指定的字段
        # exclude=('name',) #跟fields不能都寫,寫誰,就表示排除誰
        # read_only_fields=('price',)
        # write_only_fields=('id',) #棄用了,使用extra_kwargs
        extra_kwargs = {  # 類似于這種形式name=serializers.CharField(max_length=16,min_length=4)
            'price': {'write_only': True},
        }

注冊app

路由分發(fā)

Serializer高級(jí)用法

source隱藏?cái)?shù)據(jù)庫字段,使用字段別名

  • 盡量隱藏?cái)?shù)據(jù)庫字段,保證與序列化字段名不一樣


小結(jié)

1 Serializer類,需要序列化什么,必須寫一個(gè)類繼承,想序列化什么字段,
就在里面寫字段,source的作用(很多字段類)

2 序列化queryset(列表)對象和真正的對象,many=True的作用,instance=要序列化的對象,

3 反序列化 instance=要序列化的對象,data=request.data

4 字段驗(yàn)證,序列化類中,給字段加屬性,局部和全局鉤子函數(shù),字段屬性的validators=[check_author]

5 當(dāng)在視圖中調(diào)用 序列化對象.is_valid()   
  boo_ser.is_valid(raise_exception=True) 只要驗(yàn)證不通過,直接拋異常

6 修改保存---》調(diào)用序列化對象.save(),重寫Serializer類的update方法
        def update(self, instance, validated_data):
            #instance是book這個(gè)對象
            #validated_data是校驗(yàn)后的數(shù)據(jù)
            instance.name=validated_data.get('name')
            instance.price=validated_data.get('price')
            instance.author=validated_data.get('author')
            instance.publish=validated_data.get('publish')
            instance.save()  #book.save()   django 的orm提供的
            return instance

7 序列化得到字典,序列化對象.data  

8 自己定義了一個(gè)Response對象
    class MyResponse():
        def __init__(self):
            self.status=100
            self.msg='成功'
        @property
        def get_dict(self):
            return self.__dict__
        
9 反序列化的新增 序列化類(data=request.data),如果只傳了data,當(dāng)調(diào)用  
序列化對象.save(),會(huì)觸發(fā)序列化類的create方法執(zhí)行,
當(dāng)傳了instance和data時(shí),調(diào)用 序列化對象.save(),會(huì)觸發(fā)序列化類的update方法執(zhí)行

10 重寫create方法(可以很復(fù)雜)
        def create(self, validated_data):
            instance=Book.objects.create(**validated_data)
            return instance


11 ModelSerializer 跟Model做了一個(gè)對應(yīng)
    class BookModelSerializer(serializers.ModelSerializer):
        def validate_price(self, data):
            pass
        publish=serializers.CharField(source='publish.name')
        class Meta:
            model=Book  # 對應(yīng)上models.py中的模型
            fields='__all__'
            # fields=('name','price','id','author','publish') # 只序列化指定的字段
            # exclude=('name',) #跟fields不能都寫,寫誰,就表示排除誰
            # read_only_fields=('price',)
            # write_only_fields=('id',) #棄用了,使用extra_kwargs
            extra_kwargs = {  # 類似于這種形式name=serializers.CharField(max_length=16,min_length=4)
                'price': {'write_only': True,max_length:16,min_length:4},
                
            }
            
12 如果在ModelSerializer中寫一個(gè)局部鉤子或者全局鉤子,如何寫?
    -跟之前一模一樣

13 many=True 能夠序列化多條的原因---》__new__是在__init__之前執(zhí)行的,造出一個(gè)空對象

14 接口:統(tǒng)一子類的行為

drf-request和drf-response

  • getattr方法
定義了__getattr__(),當(dāng)訪問object不存在的屬性時(shí)會(huì)調(diào)用該方法

不定義訪問不存在的屬性時(shí)會(huì)報(bào) AttributeError

eg:

class Cat(object):
  def __init__(self):
    self.name = "jn"

  def __getattr__(self, item):
    return "tm"


cat = Cat()
print(cat.name)
print(getattr(cat, 'name'))
print("*" * 20)
print(cat.age)
print(getattr(cat, 'age'))

getattr()函數(shù)

>>> getattr(a, 'bar')        # 獲取屬性 bar 值
1
  • assert斷言該傳入的request對象是django傳入的request對象,如果不是則返回


請求對象.data:前端以三種編碼方式傳入的數(shù)據(jù),都可以取出來

text/html
application/json

請求對象..query_params 與Django標(biāo)準(zhǔn)的request.GET相同,只是更換了更正確的名稱而已。

drf-response

#from rest_framework.response import Response
 def __init__(self, data=None, status=None,
                 template_name=None, headers=None,
                 exception=False, content_type=None):
        
#data:你要返回的數(shù)據(jù),字典
#status:返回的狀態(tài)碼,默認(rèn)是200,
    -from rest_framework import status在這個(gè)路徑下,它把所有使用到的狀態(tài)碼都定義成了常量
#template_name 渲染的模板名字(自定制模板),不需要了解
#headers:響應(yīng)頭,可以往響應(yīng)頭放東西,就是一個(gè)字典
#content_type:響應(yīng)的編碼格式,application/json和text/html;

# 瀏覽器響應(yīng)成瀏覽器json格式,postman響應(yīng)成json格式,通過配置實(shí)現(xiàn)的(默認(rèn)配置)

#不管是postman還是瀏覽器,都返回json格式數(shù)據(jù)
# drf有默認(rèn)的配置文件---》先從項(xiàng)目的setting中找,找不到,采用默認(rèn)的
# drf的配置信息,先從自己類中找--》項(xiàng)目的setting中找---》默認(rèn)的找
    -局部使用:對某個(gè)視圖類有效
        -在視圖類中寫如下
        from rest_framework.renderers import JSONRenderer
        renderer_classes=[JSONRenderer,]
    -全局使用:全局的視圖類,所有請求,都有效
        -在setting.py中加入如下
        REST_FRAMEWORK = {
            'DEFAULT_RENDERER_CLASSES': (  # 默認(rèn)響應(yīng)渲染類
                'rest_framework.renderers.JSONRenderer',  # json渲染器
                'rest_framework.renderers.BrowsableAPIRenderer',  # 瀏覽API渲染器瀏覽器訪問時(shí),會(huì)返回瀏覽器格式
            )
        }
  • status響應(yīng)狀態(tài)碼


視圖

  • 可以找到api.html頁面修改當(dāng)前顯示



全局和局部配置響應(yīng)

  • 訪問視圖的查找順序


視圖

# 兩個(gè)視圖基類
APIView
GenericAPIView

基于GenericAPIView寫5個(gè)接口

# views.py
class Book2View(GenericAPIView):
    #queryset要傳queryset對象,查詢了所有的圖書
    # serializer_class使用哪個(gè)序列化類來序列化這堆數(shù)據(jù)
    queryset=Book.objects
    # queryset=Book.objects.all()
    serializer_class = BookSerializer
    def get(self,request):
        book_list=self.get_queryset()
        book_ser=self.get_serializer(book_list,many=True)

        return Response(book_ser.data)
    def post(self,request):
        book_ser = self.get_serializer(data=request.data)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.data)
        else:
            return Response({'status':101,'msg':'校驗(yàn)失敗'})


class Book2DetailView(GenericAPIView):
    queryset = Book.objects
    serializer_class = BookSerializer
    def get(self, request,pk):
        book = self.get_object()
        book_ser = self.get_serializer(book)
        return Response(book_ser.data)

    def put(self, request,pk):
        book = self.get_object()
        book_ser = self.get_serializer(instance=book,data=request.data)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.data)
        else:
            return Response({'status': 101, 'msg': '校驗(yàn)失敗'})

    def delete(self,request,pk):
        ret=self.get_object().delete()
        return Response({'status': 100, 'msg': '刪除成功'})
    
 #url.py
    # 使用GenericAPIView重寫的
    path('books2/', views.Book2View.as_view()),
    re_path('books2/(?P<pk>\d+)', views.Book2DetailView.as_view()),
  • GenericAPIView源碼




    -GenricApiView的好處


基于GenericAPIView和5個(gè)視圖擴(kuò)展類寫的接口

from rest_framework.mixins import  ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin
# views.py
class Book3View(GenericAPIView,ListModelMixin,CreateModelMixin):

    queryset=Book.objects
    serializer_class = BookSerializer
    def get(self,request):
        return self.list(request)

    def post(self,request):
        return self.create(request)

class Book3DetailView(GenericAPIView,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin):
    queryset = Book.objects
    serializer_class = BookSerializer
    def get(self, request,pk):
        return self.retrieve(request,pk)

    def put(self, request,pk):
        return self.update(request,pk)

    def delete(self,request,pk):
        return self.destroy(request,pk)
# urls.py
    # 使用GenericAPIView+5 個(gè)視圖擴(kuò)展類  重寫的
    path('books3/', views.Book3View.as_view()),
    re_path('books3/(?P<pk>\d+)', views.Book3DetailView.as_view()),

GenericApiView的9個(gè)視圖子類

  • 進(jìn)一步省略代碼
  • 使用繼承就可以使用


  • get


  • post


  • 最終代碼



retrieve獲取一條,listApiView獲取多條
1.2.3 GenericAPIView的視圖子類
1)CreateAPIView
提供 post 方法

繼承自: GenericAPIView、CreateModelMixin

2)ListAPIView
提供 get 方法

繼承自:GenericAPIView、ListModelMixin

3)RetrieveAPIView
提供 get 方法

繼承自: GenericAPIView、RetrieveModelMixin

4)DestoryAPIView
提供 delete 方法

繼承自:GenericAPIView、DestoryModelMixin

5)UpdateAPIView
提供 put 和 patch 方法

繼承自:GenericAPIView、UpdateModelMixin

6)RetrieveUpdateAPIView
提供 get、put、patch方法

繼承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin

7)RetrieveUpdateDestoryAPIView
提供 get、put、patch、delete方法

繼承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin

使用ModelViewSet編寫5個(gè)接口

  • 源碼分析


  • viewsets重寫了路由的as_view方法




  • 最終代碼:路由增加一個(gè)參數(shù),來區(qū)分get一條或者多條




    代碼

# views.py
from rest_framework.viewsets import ModelViewSet
class Book5View(ModelViewSet):  #5個(gè)接口都有,但是路由有點(diǎn)問題
    queryset = Book.objects
    serializer_class = BookSerializer
    
# urls.py
# 使用ModelViewSet編寫5個(gè)接口
    path('books5/', views.Book5View.as_view(actions={'get':'list','post':'create'})), #當(dāng)路徑匹配,又是get請求,會(huì)執(zhí)行Book5View的list方法
    re_path('books5/(?P<pk>\d+)', views.Book5View.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})),


源碼分析ViewSetMixin

Python全棧開發(fā)29期_嗶哩嗶哩 (゜-゜)つロ 干杯~-bilibili

# 重寫了as_view
# 核心代碼(所以路由中只要配置了對應(yīng)關(guān)系,比如{'get':'list'}),當(dāng)get請求來,就會(huì)執(zhí)行l(wèi)ist方法
for method, action in actions.items():
    #method:get
    # action:list
    handler = getattr(self, action)
    #執(zhí)行完上一句,handler就變成了list的內(nèi)存地址
    setattr(self, method, handler)
    #執(zhí)行完上一句  對象.get=list
    #for循環(huán)執(zhí)行完畢 對象.get:對著list   對象.post:對著create

繼承viewsetmixin視圖類

  • 自定義get方法使用某個(gè)函數(shù)
# views.py
from rest_framework.viewsets import ViewSetMixin
class Book6View(ViewSetMixin,APIView): #一定要放在APIVIew前,也可以繼承g(shù)enricapiview
    def get_all_book(self,request):
        print("xxxx")
        book_list = Book.objects.all()
        book_ser = BookSerializer(book_list, many=True)
        return Response(book_ser.data)
    
# urls.py
    #繼承ViewSetMixin的視圖類,路由可以改寫成這樣
    path('books6/', views.Book6View.as_view(actions={'get': 'get_all_book'})),

https://tva1.sinaimg.cn/large/007S8ZIlgy1ggipvctuxcj31wc0goq89.jpg

總結(jié)

1 請求和響應(yīng)
2 請求 Request對象,drf新包裝的,Request.data,Request.query_params, 重寫了getattr, request._request
3 json模塊是否執(zhí)行反序列化bytes格式
4 考你:視圖類的方法中:self.request,就是當(dāng)次請求的request
5 Response:類,實(shí)例化傳一堆參,data=字典,status=狀態(tài)碼(有一堆常量),headers=響應(yīng)頭(字典),content_type=響應(yīng)的編碼方式
6 全局和局部配置,響應(yīng)格式
7 drf默認(rèn)配置文件,查找順序--》先從類中屬性找---》項(xiàng)目的setting找---》drf默認(rèn)的配置找



# 8 視圖家族
    -APIView---》繼承自View
    -GenicAPIView---》APIView,做了一些擴(kuò)展:
        -queryset = None
        -serializer_class = None
        -get_queryset()  經(jīng)常用
        -get_serializer() 經(jīng)常用
        -get_serializer_class() 內(nèi)部來用,外部會(huì)重寫
        -get_object()  經(jīng)常用,獲取一條數(shù)據(jù)(pk傳過來)
            -源碼解析
            queryset = self.filter_queryset(self.get_queryset()) #返回所有數(shù)據(jù)queryset對象
            # lookup_url_kwarg就是pk,路由中有名分組分出來的pk
            lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
            # {pk:4}  4 瀏覽器地址中要查詢的id號(hào)http://127.0.0.1:8000/books6/4/
            filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
            # 根據(jù)pk=4去queryset中g(shù)et單個(gè)對象
            obj = get_object_or_404(queryset, **filter_kwargs)
            self.check_object_permissions(self.request, obj)
            return obj
   -5 個(gè)視圖擴(kuò)展類(繼承了object),每個(gè)里面寫了一個(gè)方法(ListModelMixin:list方法)       
        ListModelMixin,
        CreateModelMixin,
        UpdateModelMixin,
        DestroyModelMixin,
        RetrieveModelMixin
   -GenericAPIView的視圖子類,9個(gè),繼承了GenicAPIView+一個(gè)或者兩個(gè)或者三個(gè)視圖擴(kuò)展類
        CreateAPIView,
        ListAPIView,
        UpdateAPIView,
        RetrieveAPIView,
        DestroyAPIView,
        ListCreateAPIView,
        RetrieveUpdateDestroyAPIView,
        RetrieveDestroyAPIView,
        RetrieveUpdateAPIView
  -視圖集:ModelViewSet,ReadOnlyModelViewSet:繼承了上面一堆(5個(gè)視圖擴(kuò)展和GenicAPIView)+自己寫了一個(gè)ViewSetMixin(as_view方法),只要繼承它的,路由得寫成{‘get’:‘自己定義的方法’}
    -ViewSet=ViewSetMixin, views.APIView :ViewSetMixin要放在前面
    -GenericViewSet=ViewSetMixin+GenicAPIView
    
    -ViewSetMixin(as_view方法)
    -ViewSetMixin+APIView=ViewSet
    -ViewSetMixin+GenicAPIView=GenericViewSet

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • drf使用記錄(三) - 視圖 視圖之前還忘記了點(diǎn)啥 模型類序列化器 DRF為我們提供了ModelSerializ...
    憧憬001閱讀 765評(píng)論 0 1
  • 1. 版本 了解* 可以放在url,這種是比較推薦的。它需要配套的路由,一般所有的CBV都要使用,所以放在全局配...
    上帝大人閱讀 193評(píng)論 0 1
  • Rest中的View (1)使用Drf中的Serializer 其他的包 其中django-guardian是用來...
    何阿駝閱讀 2,453評(píng)論 0 6
  • 久違的晴天,家長會(huì)。 家長大會(huì)開好到教室時(shí),離放學(xué)已經(jīng)沒多少時(shí)間了。班主任說已經(jīng)安排了三個(gè)家長分享經(jīng)驗(yàn)。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,822評(píng)論 16 22
  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友。感恩相遇!感恩不離不棄。 中午開了第一次的黨會(huì),身份的轉(zhuǎn)變要...
    余生動(dòng)聽閱讀 10,858評(píng)論 0 11

友情鏈接更多精彩內(nèi)容