2021-02-08

参考博客

[置顶]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)
```python
```python
# from rest_framework.serializers import Serializer  # 就是一个类
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=[] 列表中写函数内存地址
    publish=serializers.CharField()

    def validate_price(self, data):   # validate_字段名  接收一个参数
        #如果价格小于10,就校验不通过
        # print(type(data))
        # print(data)
        if float(data)>10:
            return data
        else:
            #校验失败,抛异常
            raise ValidationError('价格太低')
    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这个对象
        #validated_data是校验后的数据
        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  # 对应上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},
        }
```python
# app01/views.py
```python
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 提供的响应对象

# 导入自己写的response类
from app01.utils import MyResponse
class BookView(APIView):
    def get(self,request,pk):
        book=Book.objects.filter(id=pk).first()
        #用一个类,毫无疑问,一定要实例化
        #要序列化谁,就把谁传过来
        book_ser=BookSerializer(book)  # 调用类的__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':'成功'}
        # 找到这个对象
        book = Book.objects.filter(id=pk).first()
        # 得到一个序列化类的对象
        # boo_ser=BookSerializer(book,request.data)
        boo_ser=BookSerializer(instance=book,data=request.data)

        # 要数据验证(回想form表单的验证)
        if boo_ser.is_valid():  # 返回True表示验证通过
            boo_ser.save()  # 报错
            response_msg['data']=boo_ser.data
        else:
            response_msg['status']=101
            response_msg['msg']='数据校验失败'
            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)  # 这个按位置传request.data会给instance,就报错了
        # 校验字段
        if book_ser.is_valid():
            book_ser.save()
            response_msg['data']=book_ser.data
        else:
            response_msg['status']=102
            response_msg['msg']='数据校验失败'
            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)


```python
## APIView源码分析
![](https://img-blog.csdnimg.cn/img_convert/fe832fbe4889b0b4422dd1178b552b41.png)
![](https://img-blog.csdnimg.cn/img_convert/46f490df97cbb0a0afc7dc7d780dcecb.png)

## drf的Request类
![](https://img-blog.csdnimg.cn/img_convert/e6a932ce5c2832ae6667cbe53a9fd621.png)
![](https://img-blog.csdnimg.cn/img_convert/01136e7596344a26e79848760388a097.png)

# drf序列化
##序列化与反序列化介绍
![](https://img-blog.csdnimg.cn/img_convert/a55cb4cb2a3575493e86150444bcac4a.png)

![](https://img-blog.csdnimg.cn/img_convert/a21e5ae98d89b07cb2e8224ca57a47f8.png)
![](https://img-blog.csdnimg.cn/img_convert/b32cebe8a5793cfec76c031f195e8872.png)
![](https://img-blog.csdnimg.cn/img_convert/af4501836b5fb59b62f0cad8bef66cd0.png)

```python
需要在installed_app中注册一下'rest_framework',不然报错,如果使用Jsonresponse返回,则可以不用注册

序列化对象.data直接拿到json数据
```python
```python
可以将rest_framework的response替换成jsonresponse,前者只是给返回的数据做了一个界面美化。
```python

## 序列化字段的类型
使用charfield就返回字符串格式的json
![](https://img-blog.csdnimg.cn/img_convert/c3e9b0014ba5c10c4718db2401c1c33b.png)
- 数据库定义的字段类型和序列化类写的字段可以不一样,都用charfield没问题
![](https://img-blog.csdnimg.cn/img_convert/371176bc7b1ec877270b5bc88a6913d6.png)
- 路由
![](https://img-blog.csdnimg.cn/img_convert/f77dae5a0b051268f97312ce65878b34.png)
- 序列化器
- 需要查看哪些字段就写哪些字段
![](https://img-blog.csdnimg.cn/img_convert/bf71a5319e2993d9e7455075bf37f1dd.png)
- 字段选择
![](https://img-blog.csdnimg.cn/img_convert/05404f5c1c18d5da4a95bac77151fe9a.png)
- 将从数据库取出的数据传给序列化器,再使用response转成json返回(使用drf带的response需要先把rf注册到app,否则报错模板不存在)
![](https://img-blog.csdnimg.cn/img_convert/49a77cb4b34aabdfe1937405ba24729a.png)

## 序列化字段选项
- 使用接口,put,post数据时做数据校验
![](https://img-blog.csdnimg.cn/img_convert/60f2ffe6ad557ac5ebe6efb8e17860fc.png)
![](https://img-blog.csdnimg.cn/img_convert/2face006f5fb7c3afb55026055d832da.png)
- put方法修改数据
- 之前的修改数据方式
![](https://img-blog.csdnimg.cn/img_convert/665b9f659adecd7311bd39231644d6ef.png)
![](https://img-blog.csdnimg.cn/img_convert/aba7cbe652f2a4000d3755a0dda03813.png)


- 接口规范控制:抽象类abc、抛异常
![](https://img-blog.csdnimg.cn/img_convert/68ad1e6bdbd8e15b955c29a697d0224b.png)
![](https://img-blog.csdnimg.cn/img_convert/2cfa487f5f072374a6bf4474ba0eab2a.png)
- 重写update,更新数据
![](https://img-blog.csdnimg.cn/img_convert/4a3860d07bffb154c807382188ee5680.png)
- 集成的父类中有这个父类内部调用这个方法,优先使用重写的这个方法
![](https://img-blog.csdnimg.cn/img_convert/d567b69dd1d089e05d5dada45d4f5151.png)

## 序列化组件修改数据
![](https://img-blog.csdnimg.cn/img_convert/f3dd149d90e508339883ce2c33ed2747.png)
## 自定义校验:局部钩子、全局钩子校验:指定字段校验(类似form)
```python
数据保存之前,可以使用钩子校验规则
validate_字段名     #局部钩子
validate # 全局钩子
```python
![](https://img-blog.csdnimg.cn/img_convert/df80c21dbb1f5e49064f76ea4d510837.png)

## 字段访问控制
- readonly只可以查看,不可以写的字段
- writeonly只可以写,不可以查
```python
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=[] 列表中写函数内存地址
    publish=serializers.CharField()
```python
- get
- 序列化多条加many
```python
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)
```python
- 新增post
- 需要修改序列化类的create方法
```python
ser.py
# from rest_framework.serializers import Serializer  # 就是一个类
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=[] 列表中写函数内存地址
    publish=serializers.CharField()

    def validate_price(self, data):   # validate_字段名  接收一个参数
        #如果价格小于10,就校验不通过
        #如果价格小于10,就校验不通过
        # print(type(data))
        # print(data)
        if float(data)>10:
            return data
        else:
            #校验失败,抛异常
            raise ValidationError('价格太低')
    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这个对象
        #validated_data是校验后的数据
        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)  # 这个按位置传request.data会给instance,就报错了
        # 校验字段
        if book_ser.is_valid():
            book_ser.save()
            response_msg['data']=book_ser.data
        else:
            response_msg['status']=102
            response_msg['msg']='数据校验失败'
            response_msg['data']=book_ser.errors
        return Response(response_msg)
```python
- 修改put
- 需要传book实例
- 需要重写update方法
```python
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':'成功'}
        # 找到这个对象
        book = Book.objects.filter(id=pk).first()
        # 得到一个序列化类的对象
        # boo_ser=BookSerializer(book,request.data)
        boo_ser=BookSerializer(instance=book,data=request.data)

        # 要数据验证(回想form表单的验证)
        if boo_ser.is_valid():  # 返回True表示验证通过
            boo_ser.save()  # 报错
            response_msg['data']=boo_ser.data
        else:
            response_msg['status']=101
            response_msg['msg']='数据校验失败'
            response_msg['data']=boo_ser.errors

        return Response(response_msg)
```python
- delete删除
- 直接操作book对象,不需要重写方法
```python
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)
```python

- 类封装返回信息
```python
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)
```python
![](https://img-blog.csdnimg.cn/img_convert/52a3549eefe0b25451e313f9220977dd.png)
- 类封装返回信息的使用
![](https://img-blog.csdnimg.cn/img_convert/162de20e1b21a63d436b3f87c6bbcab9.png)

# 模型类的序列化器
- app/views.py
```python
from rest_framework.views import APIView
from app01.models import Book
from app01.ser import BookModelSerializer
from rest_framework.response import Response  #drf 提供的响应对象
# 导入自己写的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)
```python
- app/ser.py
- 对应上models.py中的模型,不需重写update和create
```python
from rest_framework import serializers
class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model=Book  # 对应上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},
        }
```python
- 不需要重写update和create了
![](https://img-blog.csdnimg.cn/img_convert/4ee9739a3b2878d0cdcbfb0d7e8a4a2c.png)
- bookmodelser源码
- 序列化多条需要传many=true
- 加了many=true参数生成的是不同的对象
![](https://img-blog.csdnimg.cn/img_convert/7edfa0505e878deb62398323a0f40bed.png)
![](https://img-blog.csdnimg.cn/img_convert/9be82be6babeaeed8bcde908805eaa82.png)



# 注册app
![](https://img-blog.csdnimg.cn/img_convert/e783062c875e256186fbe70e0afdb827.png)

# 路由分发
- 先匹配总路由,再匹配多个app的路由
- include
[Django--路由控制 - 刘清政 - 博客园](https://www.cnblogs.com/liuqingzheng/articles/9509792.html)
![](https://img-blog.csdnimg.cn/img_convert/96e0875e4660a03f1db07724f610461e.png)


# Serializer高级用法 
## source隐藏数据库字段,使用字段别名
- 尽量隐藏数据库字段,保证与序列化字段名不一样
![](https://img-blog.csdnimg.cn/img_convert/c69640314296bd31ef2d0891c51deba5.png)

# 小结
```python
1 Serializer类,需要序列化什么,必须写一个类继承,想序列化什么字段,
就在里面写字段,source的作用(很多字段类)

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

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

4 字段验证,序列化类中,给字段加属性,局部和全局钩子函数,字段属性的validators=[check_author]

5 当在视图中调用 序列化对象.is_valid()   
  boo_ser.is_valid(raise_exception=True) 只要验证不通过,直接抛异常

6 修改保存---》调用序列化对象.save(),重写Serializer类的update方法
	    def update(self, instance, validated_data):
            #instance是book这个对象
            #validated_data是校验后的数据
            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 自己定义了一个Response对象
	class MyResponse():
        def __init__(self):
            self.status=100
            self.msg='成功'
        @property
        def get_dict(self):
            return self.__dict__
        
9 反序列化的新增 序列化类(data=request.data),如果只传了data,当调用  
序列化对象.save(),会触发序列化类的create方法执行,
当传了instance和data时,调用 序列化对象.save(),会触发序列化类的update方法执行

10 重写create方法(可以很复杂)
	    def create(self, validated_data):
            instance=Book.objects.create(**validated_data)
            return instance


11 ModelSerializer 跟Model做了一个对应
	class BookModelSerializer(serializers.ModelSerializer):
        def validate_price(self, data):
            pass
        publish=serializers.CharField(source='publish.name')
        class Meta:
            model=Book  # 对应上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中写一个局部钩子或者全局钩子,如何写?
	-跟之前一模一样

13 many=True 能够序列化多条的原因---》__new__是在__init__之前执行的,造出一个空对象

14 接口:统一子类的行为
```python

# drf-request和drf-response
- __getattr__方法
```python
定义了__getattr__(),当访问object不存在的属性时会调用该方法

不定义访问不存在的属性时会报 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'))
```python
getattr()函数
```python
>>> getattr(a, 'bar')        # 获取属性 bar 值
1
```python
![](https://img-blog.csdnimg.cn/img_convert/f93ec13503db0a238dee0657eed4e842.png)

- assert断言该传入的request对象是django传入的request对象,如果不是则返回
![](https://img-blog.csdnimg.cn/img_convert/c45bd7da9e213913d8d892d593e8edf0.png)

 请求对象.data:前端以三种编码方式传入的数据,都可以取出来
```python
text/html
application/json
```python
 请求对象..query_params 与Django标准的request.GET相同,只是更换了更正确的名称而已。

# drf-response
```python
#from rest_framework.response import Response
 def __init__(self, data=None, status=None,
                 template_name=None, headers=None,
                 exception=False, content_type=None):
        
#data:你要返回的数据,字典
#status:返回的状态码,默认是200,
	-from rest_framework import status在这个路径下,它把所有使用到的状态码都定义成了常量
#template_name 渲染的模板名字(自定制模板),不需要了解
#headers:响应头,可以往响应头放东西,就是一个字典
#content_type:响应的编码格式,application/json和text/html;

# 浏览器响应成浏览器json格式,postman响应成json格式,通过配置实现的(默认配置)

#不管是postman还是浏览器,都返回json格式数据
# drf有默认的配置文件---》先从项目的setting中找,找不到,采用默认的
# drf的配置信息,先从自己类中找--》项目的setting中找---》默认的找
	-局部使用:对某个视图类有效
        -在视图类中写如下
        from rest_framework.renderers import JSONRenderer
        renderer_classes=[JSONRenderer,]
    -全局使用:全局的视图类,所有请求,都有效
    	-在setting.py中加入如下
        REST_FRAMEWORK = {
            'DEFAULT_RENDERER_CLASSES': (  # 默认响应渲染类
                'rest_framework.renderers.JSONRenderer',  # json渲染器
                'rest_framework.renderers.BrowsableAPIRenderer',  # 浏览API渲染器浏览器访问时,会返回浏览器格式
            )
        }
```python
![](https://img-blog.csdnimg.cn/img_convert/83d022841e347e5a3b24deb1acc2e31a.png)

- status响应状态码
![](https://img-blog.csdnimg.cn/img_convert/8655eb710ed9876e1bb1717edbd08c91.png)
# 视图

- 可以找到api.html页面修改当前显示
![](https://img-blog.csdnimg.cn/img_convert/727aca3fa451ff3a9b552b64d688debd.png)
![](https://img-blog.csdnimg.cn/img_convert/8e7127598271e0e85821285550478a02.png)

# 全局和局部配置响应
- 访问视图的查找顺序
![](https://img-blog.csdnimg.cn/img_convert/6afeaaa6bb60ff9e36dd095aae22ae62.png)

# 视图
```python
# 两个视图基类
APIView
GenericAPIView
```python
## 基于GenericAPIView写5个接口
```python
# views.py
class Book2View(GenericAPIView):
    #queryset要传queryset对象,查询了所有的图书
    # serializer_class使用哪个序列化类来序列化这堆数据
    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':'校验失败'})


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': '校验失败'})

    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()),
```python
- GenericAPIView源码
![](https://img-blog.csdnimg.cn/img_convert/a913ed40ec438b8eebb460291b52297f.png)
![](https://img-blog.csdnimg.cn/img_convert/cbad2a8b696515cf5424735c1d57bc25.png)
-GenricApiView的好处
![](https://img-blog.csdnimg.cn/img_convert/0fa6bfb17ec32c6e2d1d058235f07105.png)

## 基于GenericAPIView和5个视图扩展类写的接口
![](https://img-blog.csdnimg.cn/img_convert/25142a3f3b0f379ec0082b3275161c07.png)
```python
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 个视图扩展类  重写的
    path('books3/', views.Book3View.as_view()),
    re_path('books3/(?P<pk>\d+)', views.Book3DetailView.as_view()),
```python

## GenericApiView的9个视图子类
- 进一步省略代码
- 使用继承就可以使用
![](https://img-blog.csdnimg.cn/img_convert/dab4f60bc2eaadfa43a362deed1ef49a.png)
- get
![](https://img-blog.csdnimg.cn/img_convert/e0044c624d61b56a6dcd35e814c0b61d.png)
- post
![](https://img-blog.csdnimg.cn/img_convert/a33f9b20068ede013065330a76fa3325.png)
- 最终代码
![](https://img-blog.csdnimg.cn/img_convert/f66d308022adc02f2e6e0ca3baec04fc.png)
![](https://img-blog.csdnimg.cn/img_convert/f1e16c6117f52f8de6586aef241b72ef.png)
```python
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
```python

## 使用ModelViewSet编写5个接口
- 源码分析
![](https://img-blog.csdnimg.cn/img_convert/4cb12095d33e3d315f08cf74127a9cab.png)
- viewsets重写了路由的as_view方法
![](https://img-blog.csdnimg.cn/img_convert/13c2965abff47e89fabd1be72634127a.png)
![](https://img-blog.csdnimg.cn/img_convert/3bb006493769360e343eeda651a0c85c.png)
![](https://img-blog.csdnimg.cn/img_convert/ac3af4563ac06f037b5c8dc90dacb690.png)
- 最终代码:路由增加一个参数,来区分get一条或者多条
![](https://img-blog.csdnimg.cn/img_convert/56d9c04e1a015031af7b87121546da4a.png)
![](https://img-blog.csdnimg.cn/img_convert/56b6d8e61ccf9cc0a4b9fecfead390be.png)
代码
```python
# views.py
from rest_framework.viewsets import ModelViewSet
class Book5View(ModelViewSet):  #5个接口都有,但是路由有点问题
    queryset = Book.objects
    serializer_class = BookSerializer
    
# urls.py
# 使用ModelViewSet编写5个接口
    path('books5/', views.Book5View.as_view(actions={'get':'list','post':'create'})), #当路径匹配,又是get请求,会执行Book5View的list方法
    re_path('books5/(?P<pk>\d+)', views.Book5View.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})),


```python
# 源码分析ViewSetMixin
[Python全栈开发29期_哔哩哔哩 (-)つロ 干杯~-bilibili](https://www.bilibili.com/video/BV1QE41147hU?p=921&spm_id_from=pageDriver)
![](https://img-blog.csdnimg.cn/img_convert/e30cbbf1de2a80db2b54b25903cc8e61.png)
```python
# 重写了as_view
# 核心代码(所以路由中只要配置了对应关系,比如{'get':'list'}),当get请求来,就会执行list方法
for method, action in actions.items():
    #method:get
    # action:list
    handler = getattr(self, action)
    #执行完上一句,handler就变成了list的内存地址
    setattr(self, method, handler)
    #执行完上一句  对象.get=list
    #for循环执行完毕 对象.get:对着list   对象.post:对着create
```python

# 继承viewsetmixin视图类
- 自定义get方法使用某个函数
```python
# views.py
from rest_framework.viewsets import ViewSetMixin
class Book6View(ViewSetMixin,APIView): #一定要放在APIVIew前,也可以继承genricapiview
    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'})),

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值