首页 > 编程语言 >drf-day5——反序列化类校验部分源码分析、断言、drf请求、drf响应、视图组件及两个视图基类、基于GenericAPIView+5个视图扩展类

drf-day5——反序列化类校验部分源码分析、断言、drf请求、drf响应、视图组件及两个视图基类、基于GenericAPIView+5个视图扩展类

时间:2023-02-03 21:13:01浏览次数:64  
标签:name models self request 视图 import 序列化 class drf

目录

一、反序列化类校验部分源码解析(了解)

反序列化校验,什么时候,开始执行校验(切入点)

	-视图类中的 ser.is_valid(),就会执行校验,校验通过返回True,不通过返回False

image-20230203092941210

入口:ser.is_valid() 是序列化类的对象,假设序列化类是BookSerializer---》我们在他的内部找is_valid---》找不到,找到父类的父类BaseSerializer中有is_valid :【raise_exception:先注意,它的作用就是替代视图层中的if判断,当我们的程序运行is_valid的结果时False的时候会直接抛出异常】

   def is_valid(self, *, raise_exception=False):
    
        if not hasattr(self, '_validated_data'):
            try:
                # self序列化类的对象,属性中没有_validated_data,一定会走这句【核心】
                self._validated_data = self.run_validation(self.initial_data)
            except ValidationError as exc:
                self._validated_data = {}
                self._errors = exc.detail
            else:
                self._errors = {}

        if self._errors and raise_exception:
            raise ValidationError(self.errors)

        return not bool(self._errors)
'上面的代码我们简单区分一下可以分成两块,断言部分可以不管,当没有_validated_data这个属性或方法的时候会对他进行异常捕获。另一部分就是添加errors的错误信息并报错。通过这里我们可以猜到,执行序列化功能的代码肯定就是异常捕获那里了,而他的代码中运行了一个run_validation,这就是我们要研究的目标'
# self._validated_data = self.run_validation(self.initial_data) 核心--》self序列化类的对象
	-切记一定不要按住ctrl键点击,直接点会去Fields.py文件中的run_validation
    -真正的执行顺序是,从下往上找,对象中找不到,再往父类上一层层找
    -最终从Serializer类中找到了run_validation,而不是Fields.py文件中找到的run_validation

image

    def run_validation(self, data=empty):
        # 字段自己的,validates方法(就是执行字段中的约束条件,对他们进行校验)
        (is_empty_value, data) = self.validate_empty_values(data)
        if is_empty_value:
            return data
        # 局部钩子----【局部钩子】(ctrl点进来后我们可以发现他的代码中有反射,用getattr去找validate_开头的方法,回顾一下drf中的局部钩子,两者命名格式一样,因此这里就是局部钩子)
        value = self.to_internal_value(data)
        try:
            
            self.run_validators(value)
            # 全局钩子--》如果在BookSerializer中写了validate,优先走它,非常简单,ctril点进去我们可以看到他其实啥都没做就把数据返回出去了,但是当我们自定义后,就会现用我们定义的全局钩子进行校验
            value = self.validate(value)
 
        except (ValidationError, DjangoValidationError) as exc:
            raise ValidationError(detail=as_serializer_error(exc))

        return value
    
# 局部钩子  self.to_internal_value(data)    ---》self是BookSerializer的对象,从根上找
     def to_internal_value(self, data):
        ret = OrderedDict()
        errors = OrderedDict()
        fields = self._writable_fields
        # fields写在序列化类中一个个字段类的对象,即我们常说的字段名称
        for field in fields:
            # self BookSerializer的对象,反射validate_name
            validate_method = getattr(self, 'validate_' + field.field_name, None)
            try:
                # 在执行BookSerializer类中的validate_name方法,传入了要校验的数据
               validated_value = validate_method(validated_value)
            except ValidationError as exc:
                errors[field.field_name] = exc.detail
          
            else:
                set_value(ret, field.source_attrs, validated_value)

        if errors:
            raise ValidationError(errors)

        return ret

二、断言

详见博客:https://www.cnblogs.com/zhihuanzzh/p/16796885.html

# 我们可以发现源码中大量使用try和断言

# 关键字assert ,有什么作用?
# 我断定你是xx,如果不是就抛异常


name = 'lqz'

# if name == 'lqz':
#     print('对了')
# else:
#     # print('错了')
#     raise Exception('名字不为lqz,不能继续走了')


assert name=='lqz'   # 断定是,如果不是,就抛异常

print('后续代码')

三、drf之请求

3.1 Request能够解析的前端传入的编码格式

需求:该接口只能接收json格式,不能接收其他格式

方式一:在继承自APIView及其子类的的视图类中配置(局部配置)

# 总共有三个:from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
class BookView(APIView):
    parser_classes = [JSONParser,]
    '我们在APIView中可以看到一个属性叫做parser_classes,ctrl点击他后面的方法DEFAULT_PARSER_CLASSES,我们可以看到并不能直接点进来,但是这里我们可以去rest_frameword的配置文件中找,找到一个叫settings.py的文件就能在内部找到DEFAULT_PARSER_CLASSES,他的使用当时也是类似我们配置文件中的注册,'

image

方式二:在配置文件中配置(影响所有,全局配置)

	-django有套默认配置,每个项目有个配置
    -drf有套默认配置,每个项目也有个配置---》就在django的配置文件中
    REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        # 'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        # 'rest_framework.parsers.MultiPartParser',
    ],
}

image

方式三:全局配了1个,某个视图类想要3个,怎么配?

	-只需要在视图类,配置3个即可
    -因为:先从视图类自身找,找不到,去项目的drf配置中找,再找不到,去drf默认的配置找

3.2 Request类有哪些属性和方法(学过)

常用参数

  • data

POST、PUT、PATCH请求方式解析后的数据。(原生django的PUT请求在request.POST中取不到。)

  • query_params

与原生的GET一样。

  • 其他的方法和原来的request使用方法一致:

底层原理:在Request实例化对象时,self._request = request,将原来的request对象给了Request的对象,又在Request类中定义了__getattr__魔法方法,当在视图函数中获取request对象的属性和方法时,找不到会触发魔法方法的执行,利用反射获取原来的request对象中的方法。

def __getattr__(self, attr):
    """
    If an attribute does not exist on this instance, then we also attempt
    to proxy it to the underlying HttpRequest object.
    """
    try:
        return getattr(self._request, attr)
    except AttributeError:
        return self.__getattribute__(attr)

Response类的实例化参数

data:列表或者字典,序列化成json字符串返回给前端
status:响应状态码,默认是200:from rest_framework.status import HTTP_200_OK
headers :响应头,以字典的形式返回给前端
content_type :响应的编码格式
template_name :指定模板

class Test(APIView):
def get(self, request):
    return Response(data={}, status=status.HTTP_201_CREATED, headers={'name': 'jasper'})

四、drf之响应

4.1 Response能够响应的编码格式

# drf  是djagno的一个app,所以要注册,不注册的话不能用浏览器访问接口
# drf的响应,如果使用浏览器和postman访问同一个接口,返回格式是不一样的(浏览器会报错,postman返回数据)
	-drf做了个判断,如果是浏览器,好看一些,如果是postman只要json数据
    
    
# 方式一:在视图类中写(局部配置)
	-两个响应类---》找---》drf的配置文件中找--》两个类(也是在rest_framework的settings.py文件中)
    -from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
    class BookView(APIView):
    	renderer_classes=[JSONRenderer,]

# 方式二:在项目配置文件中写(全局配置)
    REST_FRAMEWORK = {
      'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ],
}
    
# 方式三:使用顺序(一般就用内置的即可)
	优先使用视图类中的配置,其次使用项目配置文件中的配置,最后使用内置的

4.2 Resposne的源码属性或方法

# drf 的Response 源码分析
	-from rest_framework.response import Response
    -视图类的方法返回时,retrun Response ,走它的__init__,init中可以传什么参数
    
    
# Response init可以传的参数
    def __init__(self, 
                 data=None, 
                 status=None,
                 template_name=None, 
                 headers=None,
                 exception=False, 
                 content_type=None)
    
   -data:之前咱们写的ser.data  可以是字典或列表,字符串---》序列化后返回给前端---》前端在响应体中看到的就是这个 
   -status:http响应的状态码,默认是200,你可以改
        -drf在status包下,把所有http响应状态码都写了一遍,常量
        -from rest_framework.status import HTTP_200_OK
        -Response('dddd',status=status.HTTP_200_OK)
        
   -template_name:了解即可,修改响应模板的样子,BrowsableAPIRenderer定死的样子,后期公司可以自己定制
   -headers:响应头,http响应的响应头
    	-考你,原生djagno,如何像响应头中加东西
            # 四件套 render,redirect,HttpResponse,JsonResponse
            obj = HttpResponse('dddd')
            obj['xxc'] = 'yyc'
            return obj
        
   -content_type :响应编码格式,一般不动
    
    
    
  # 重点:data,status,headers

五、视图组件介绍及两个视图基类

# drf 视图,视图类,学过APIView,drf的基类,drf提供的最顶层的类

# APIView跟之前的View区别
    -传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
    -视图方法可以返回REST framework的Response对象-
    -任何APIException异常都会被捕获到,并且处理成合适的响应信息;
    -在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制
    
    
# 两个视图基类
	APIVIew
    	-类属性:
            renderer_classes # 响应格式
    		parser_classes #能够解析的请求格式
    		authentication_classes#认证类
    		throttle_classes#频率类
    		permission_classes#权限类
    	-基于APIView+ModelSerializer+Resposne写5个接口
        	-详见代码

5.1 APIView+ModelSerializer+Resposne写5个接口

5.1.1 视图类

from .models import Book
from .serializer import BookSerializer


class BookView(APIView):
    def get(self, request):
        books = Book.objects.all()
        ser = BookSerializer(instance=books, many=True)
        return Response(ser.data)

    def post(self, request):
        ser = BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            # 咱们现在只有ser序列化类的对象,但是咱们想要,新增的对象---》序列化成字典---》大前提,序列化类中的create方法一定要返回新增的对象
            return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
        else:
            return Response({'code': 101, 'msg': ser.errors})


class BookDetailView(APIView):
    def get(self, request, pk):
        books = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=books)
        return Response(ser.data)

    def put(self, request, pk):
        books = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=books, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
        else:
            return Response({'code': 101, 'msg': ser.errors})

    def delete(self, request, pk):
        Book.objects.filter(pk=pk).delete()
        return Response({'code': 100, 'msg': '删除成功'})

5.1.2 序列化类

### ModelSerializer的使用
class BookSerializer(serializers.ModelSerializer):
    # 跟表有关联
    class Meta:
        model = Book
        fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
        extra_kwargs = {'name': {'max_length': 8},
                        'publish_detail': {'read_only': True},
                        'author_list': {'read_only': True},
                        'publish': {'write_only': True},
                        'authors': {'write_only': True},
                        }

5.5.3 路由

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>/', views.BookDetailView.as_view()),
]

六、基于GenericAPIView+5个视图扩展类

GenericAPIView属性和方法介绍

'''
# GenericAPIView属性介绍
1 queryset:要序列化或反序列化的表模型数据
2 serializer_class:使用的序列化类
3 lookup_field :查询单条的路由分组分出来的字段名
4 filter_backends:过滤类的配置(了解)
5 pagination_class:分页类的配置(了解)

# 方法
1 get_queryset   :获取要序列化的对象
2 get_object  :获取单个对象
3 get_serializer :获取序列化类  ,跟它差不多的get_serializer_class,一般重写它,不调用它
4 filter_queryset  :过滤有关系(了解)
'''

6.1 视图类

### 咱们能不能想一种方式,通过继承,少些代码-----》GenericAPIView---》继承了APIView,有很多新的属性和方法
# 以后咱们可以基于这个类,来写5个接口
# 5个接口的效果一样,但是咱们代码 可用性变高了
# GenericAPIView 属性和方法
'''
# GenericAPIView属性介绍
1 queryset:要序列化或反序列化的表模型数据
2 serializer_class:使用的序列化类
3 lookup_field :查询单条的路由分组分出来的字段名
4 filter_backends:过滤类的配置(了解)
5 pagination_class:分页类的配置(了解)

# 方法
1 get_queryset   :获取要序列化的对象
2 get_object  :获取单个对象
3 get_serializer :获取序列化类  ,跟它差不多的get_serializer_class,一般重写它,不调用它
4 filter_queryset  :过滤有关系(了解)
'''

from rest_framework.generics import GenericAPIView

class BookView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request):
        # objs = self.queryset #这里可以拿到,但是不要这么用,GenericAPIView提供了一个方法,
        objs = self.get_queryset()  # 好处,可以重写该方法,后期可扩展性高
        # 取序列化类,不要使用self.serializer_class,而要使用方法get_serializer(从源码中看就是丰富了一下他)
        ser = self.get_serializer(instance=objs, many=True)  # 后期可以重写get_serializer_class,指定使用哪个序列化类来序列化
        return Response(ser.data)

    def post(self, request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
            # 咱们现在只有ser序列化类的对象,但是咱们想要,新增的对象---》序列化成字典---》大前提,序列化类中的create方法一定要返回新增的对象
            return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
        else:
            return Response({'code': 101, 'msg': ser.errors})


class BookDetailView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, pk):
        obj = self.get_object()  # 获取单条
        ser = self.get_serializer(instance=obj)
        return Response(ser.data)

    def put(self, request, pk):
        obj = self.get_object()
        ser = self.get_serializer(instance=obj, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
        else:
            return Response({'code': 101, 'msg': ser.errors})

    def delete(self, request, pk):
        self.get_object().delete()
        return Response({'code': 100, 'msg': '删除成功'})


### 第三册层,如果我们写Pulish的5个接口,继承自GenericAPIView,跟Book的区别只有两个类属性,我们可以再封装
### 封装了5个视图扩展类---》5个接口  get所有,get一个,post新增,put修改,delete删除
# 5个视图扩展类,没有继承APIView及其子类,它不能单独使用,必须配合GenericAPIView一起用才行
# CreateModelMixin:新增,咱们封装---》在CreateModelMixin里面写个post,但是人家不是,人家写了create方法,代码就是post的代码
# DestroyModelMixin:删除     destroy方法
# RetrieveModelMixin:查单条   retrieve方法
# ListModelMixin:查所有      list 方法
# UpdateModelMixin:更新      updata方法
from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin, \
    ListModelMixin

# 基于GenericAPIView+5个视图扩展类写接口

class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request):
        return self.list(request)

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


class BookDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)


## 再继续封装  --->使用效果变成----》  自己封装 9个
# 9个---》5个+2个+
from rest_framework.generics import ListAPIView, CreateAPIView, ListCreateAPIView
from rest_framework.generics import DestroyAPIView, UpdateAPIView, RetrieveAPIView, RetrieveUpdateDestroyAPIView, \
    RetrieveDestroyAPIView, RetrieveUpdateAPIView  # 没有DestroyUpdateAPIView

class PublishView(CreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

class BookDetailView(DestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer



# 5个接口,用同一个---》路由会有问题,有两个get---》写了个魔法类
from rest_framework.viewsets import ModelViewSet
class PublishView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

6.2 序列化类

class BookSerializer(serializers.ModelSerializer):
    # 跟表有关联
    class Meta:
        model = Book
        fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
        extra_kwargs = {'name': {'max_length': 8},
                        'publish_detail': {'read_only': True},
                        'author_list': {'read_only': True},
                        'publish': {'write_only': True},
                        'authors': {'write_only': True},
                        }

6.3 路由

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>/', views.BookDetailView.as_view()),
]

七、作业

1 基于APIView写5个接口

基于GenericAPIView

models.py

from django.db import models

# Create your models here.
class Book(models.Model):
    name = models.CharField(max_length=32, default='xx')
    price = models.CharField(max_length=32)

    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)  # 留住,还有很多
    authors = models.ManyToManyField(to='Author')

    def publish_detail(self):
        return {'name': self.publish.name, 'addr': self.publish.addr}

    def author_list(self):
        l = []
        for author in self.authors.all():
            l.append({'name': author.name, 'phone': author.phone})
        return l


class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)



class Author(models.Model):
    name = models.CharField(max_length=32)
    phone = models.CharField(max_length=11)

urls.py

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>/', views.BookDetailView.as_view()),
]

serializer.py

from rest_framework import serializers
from .models import Book, Author, Publish

class BookSerializer(serializers.ModelSerializer):
    # 跟表有关联
    class Meta:
        model = Book
        fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
        extra_kwargs = {'name': {'max_length': 8},
                        'publish_detail': {'read_only': True},
                        'author_list': {'read_only': True},
                        'publish': {'write_only': True},
                        'authors': {'write_only': True},
                        }

views.py

from django.shortcuts import render,redirect,HttpResponse
from rest_framework.generics import GenericAPIView
from .models import Book
from .serializer import BookSerializer
from rest_framework.response import Response

# Create your views here.
class BookView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    def get(self,request):
        objs = self.get_queryset()
        ser = self.get_serializer(instance=objs, many=True)
        return Response(ser.data)
    def post(self,request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code':10000,'msg':'增加成功', 'result':ser.data})
        else:
            return Response({'code':10001,'msg':ser.errors})

class BookDetailView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    def get(self,request,pk):
        objs = self.get_object()
        ser = self.get_serializer(instance=objs)
        return Response(ser.data)
    def put(self,request,pk):
        objs = self.get_object()
        ser = self.get_serializer(data=request.data,instance=objs)
        if ser.is_valid():
            ser.save()
            return Response({'code': 10000, 'msg': '修改成功', 'result': ser.data})
        else:
            return Response({'code': 10001, 'msg': ser.errors})

    def delete(self,request,pk):
        self.get_object().delete()

        return Response({'code': 10000, 'msg': '删除成功'})

基于GenericAPIView+5个视图扩展类

models.py

from django.db import models

# Create your models here.
class Book(models.Model):
    name = models.CharField(max_length=32, default='xx')
    price = models.CharField(max_length=32)

    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)  # 留住,还有很多
    authors = models.ManyToManyField(to='Author')

    def publish_detail(self):
        return {'name': self.publish.name, 'addr': self.publish.addr}

    def author_list(self):
        l = []
        for author in self.authors.all():
            l.append({'name': author.name, 'phone': author.phone})
        return l


class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)



class Author(models.Model):
    name = models.CharField(max_length=32)
    phone = models.CharField(max_length=11)

urls.py

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>/', views.BookDetailView.as_view()),
]

serializer.py

from rest_framework import serializers
from .models import Book, Author, Publish

class BookSerializer(serializers.ModelSerializer):
    # 跟表有关联
    class Meta:
        model = Book
        fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
        extra_kwargs = {'name': {'max_length': 8},
                        'publish_detail': {'read_only': True},
                        'author_list': {'read_only': True},
                        'publish': {'write_only': True},
                        'authors': {'write_only': True},
                        }

views.py

from django.shortcuts import render
from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin, \
    ListModelMixin
from rest_framework.generics import GenericAPIView
from .models import Book, Publish, Author
from .serializer import BookSerializer


# Create your views here.
class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request):
        return self.list(request)

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


class BookDetailView(GenericAPIView, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

2 剩下两层

第一层(两个视图完成功能)

    class PublishView(CreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    class BookDetailView(DestroyAPIView):
        queryset = Book.objects.all()
        serializer_class = BookSerializer

代码

models.py

from django.db import models

# Create your models here.
class Book(models.Model):
    name = models.CharField(max_length=32,default='xx')
    price = models.CharField(max_length=32)
    publish = models.ForeignKey(to='Puplish', on_delete=models.CASCADE)
    authors = models.ManyToManyField(to='Author')

    def publish_detail(self):
        return {'name':self.publish.name,'addr':self.publish.addr}
    def author_list(self):
        l = []
        for author in self.authors.all():
            l.append({'name':author.name,'phone':author.phone})
        return l


class Puplish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)


class Author(models.Model):
    name = models.CharField(max_length=32)
    phone = models.CharField(max_length=32)

urls.py

from django.shortcuts import render
from .models import Book, Puplish, Author
from rest_framework.generics import GenericAPIView, ListCreateAPIView, RetrieveUpdateDestroyAPIView
from .serializer import BookSerializer
from rest_framework.response import Response


# Create your views here.
class BookView(ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer





class BookDetailView(RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

serializer.py

from rest_framework import serializers
from .models import Book, Puplish, Author


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
        extra_kwargs = {
            'name': {'max_length': 8},
            'publish_detail': {'read_only': True},
            'author_list': {'read_only': True},
            'publish': {'write_only': True},
            'authors': {'write_only': True},
        }

views.py

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>/', views.BookDetailView.as_view()),
]

第二层带5个接口(一个视图完成五个功能)

      class PublishView(CreateAPIView):
        queryset = Book.objects.all()
        serializer_class = BookSerializer

代码

models.py

from django.db import models

# Create your models here.
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)

    publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
    authors = models.ManyToManyField(to='Author')
    def publish_detail(self):
        return {'name':self.publish.name,'addr':self.publish.addr}
    def author_list(self):
        l = []
        for author in self.authors.all():
            l.append({'name':author.name,'phone':author.phone})
        return l

class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)



class Author(models.Model):
    name = models.CharField(max_length=32)
    phone = models.CharField(max_length=11)

urls.py

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', views.BookDetailView.as_view()),
    path('books/<int:pk>/', views.BookDetailView.as_view()),
]

serializer.py

from rest_framework import serializers
from .models import Book, Publish, Author


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
        extra_kwargs = {
            'name': {'max_length': 8},
            'publish_detail': {'read_only': True},
            'author_list': {'read_only': True},
            'publish': {'write_only': True},
            'authors': {'write_only': True},
        }

views.py

from django.shortcuts import render
from .models import Book,Publish,Author
from rest_framework.generics import RetrieveUpdateDestroyAPIView,CreateAPIView
from .serializer import BookSerializer
# Create your views here.



class BookDetailView(RetrieveUpdateDestroyAPIView,CreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer


标签:name,models,self,request,视图,import,序列化,class,drf
From: https://www.cnblogs.com/zhihuanzzh/p/17089531.html

相关文章