drf-day6

发布时间 2023-09-04 16:27:58作者: Py玩家

drf之请求

1、drf之请求request类

  1.把前端携带到请求体中的数据封装到request.data中

  2.之前的request.get封装成request.query_params

  3.其他方法用起来和以前一样

  4.request.method 的时候》》》实际上 request._request.'method'》》》反射出来的这个类from rest_framework.request import Request没有method,他会触发这个类的__getattr__

2、控制前端请求的编码格式

前端传入数据的编码格式:urlencoded、json、form-data

作用:控制某些接口只能接受指定的编码格式

使用:

方式一:局部使用,在想要控制的视图类上控制,首先在局部变量中查找,找到就是用局部定义的

class BookView(APIView):
#图类内的所有方法,只能接收json格式
    parsers_classes=[JSONparser]

方式二,全局生效,所有接口都支持一种或者几种编码格式

REST-FRAMEWORK={

  'DEFAULT_PARSER_CLASSES':[

    'rest_framework.parsers.jsonparser',
    'rest_framework.parsers.formparser',
    'rest_framework.parsers.multipartparser,
   ]
}

全局使用后,想要限制某种编码格式,就在视图类上做一个局部使用即可,因为优先使用局部,也就是视图类内部定义的

ps:drf自己有默认的配置,我们不需要配置也可以使用它自带的

drf之响应

1、drf之response对象源码

class Response(SimpleTemplateResponse):

    def __init__(self, data=None, status=None,
                 template_name=None, headers=None,
                 exception=False, content_type=None):
       
        super().__init__(None, status=status)

        if isinstance(data, Serializer):
            msg = (
                'You passed a Serializer instance as data, but '
                'probably meant to pass serialized `.data` or '
                '`.error`. representation.'
            )
            raise AssertionError(msg)

        self.data = data
        self.template_name = template_name
        self.exception = exception
        self.content_type = content_type

        if headers:
            for name, value in headers.items():
                self[name] = value

response中的参数

data=none    #data=字符串、列表、字典,放在响应体中一位置传参的话,第一个参数就是它
status=none  #它主要是定义http响应状态,默认的是200,千万不能写1xx,否则报错
headers=none  # http响应头,后期我们可以往响应头中放数据


content_type=None #响应编码格式(不用管,用浏览器访问就是:text/html,用postman就是:json格式)
template_name=None #模版名字  默认是:rest_framework/api.html  了解,可以定制自己返回的页面样子

原生django,向响应头写入数据

def test(request):

    obj=Httpresponse(‘ok’)
    obj['xxx']='yyy'
    return obj

通过响应体取出数据

res=Response(data={},status=500,headers={'xxx':'yyy'})
print(res.data)
return res

取响应头

res.headers 拿不到数据,可以通过下面的方式或得到
res['xxx']
还可以通过res.has_header('zzz')判断数据是否存在

2、drf之响应格式

响应体的编码格式::默认支持json和text/html(浏览器

局部使用:

只支持json格式
class BookView(APIView):
       renderer_classes = [BrowsableAPIRenderer]

全局使用:

REST_FRAMEWORK={
    'DEFAULT_RENDERER_CLASSES':[
            'rest_framework_renderers.JSONrenderer',
            'rest_framework_BrowsableAPIRenderer',
            ],
}    

全局配置好,想限制响应编码格式,可在视图类中局部使用即可

drf有默认的响应编码格式配置

请求体中三种编码格式都可以解析

响应体中,浏览器访问有浏览器的编码格式:text/html,postman访问就是appliation/json

也就是浏览器访问看到浏览器想看到的,postman访问看到的是json格式

两个视图基类

基于APIView写接口

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

    def post(self, request):
        ser = BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()  # 反序列化保存
            return Response(ser.data)  # 创建成功后,返回创建后的对象, 做了个序列化
        else:
            return Response(ser.errors)


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

    def put(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)

    def delete(self, request, pk):
        Book.objects.filter(pk=pk).delete()
        return Response('')

 

基于GenericAPIView(只要更数据库打交道使用)

自己写的GenericAPIView类

class GenericAPIView(APIView):
    queryset = None
    serializer_class = None
    
    def get_queryset(self):
        return self.queryset.all()  # 真正使用的时候,再加all获取所有才行

    def get_serializer(self, *args, **kwargs):
        return self.serializer_class(*args, **kwargs)

    def get_object(self, pk):
        res = self.get_queryset()
        return res.filter(pk=pk).first()

GenericAPIView源码属性和方法分析

重要属性:

queryset:以后放所有某个表查询出来的数据
serializer_class:要序列化的类

重要方法:

get_queryset:要序列化的所有数据,queryset对象
get_serializer :序列化类
get_object  :修改,查询的单条的序列化的数据,queryset对象

了解属性:

ookup_field = 'pk':  路由使用转换器,转换出来的参数,查询单条要用到,如果改了,路由对应也要修改,一般不改
filter_backends:后面详细讲     过滤 功能
pagination_class :后面详细讲  分页

了解方法:

get_serializer_class  后期咱们可能会重写它,指定某些方法使用不同的序列化类
filter_queryset 后面跟过滤功能一起讲

GenericAPIView的代码展示

class PublishView(GenericAPIView):
    queryset = Publish.objects.all()  # 类只要加载,就会执行,查了所有数据,不能以它为准
    serializer_class = PublishSerializer

    def get(self, request):
        obj_list = self.get_queryset()  # 以用的时候为准
        ser = self.get_serializer(instance=obj_list, 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(ser.data)  # 创建成功后,返回创建后的对象, 做了个序列化
        else:
            return Response(ser.errors)


class PublishDetailView(GenericAPIView):
    serializer_class = PublishSerializer
    queryset = Publish.objects.all()

    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(ser.data)
        else:
            return Response(ser.errors)

    def delete(self, request, pk):
        self.get_object().delete()
        return Response('')

经常犯错的地方:

 错误1 :一定要在用数据的时候再查
def get_queryset(self):
        return self.queryset.all() 
错误2:一定要记得在视图类中配置
queryset=
serializer_class=

五个视图扩展类

drf中写出来这五种类,我们直接使用即可

RetrieveModelMixin,  查询一条,写了一个方法 retrieve,代码就是之前在视图类中写的get方法中的内容

CreateModelMixin  新增一条写了一个方法  create,代码就是 跟咱们之前写新增一条 post  方法内容一样

DestroyModelMixin,删除一条写了一个方法  destroy,码就是 跟咱们之前写新增一条 delete  方法内容一样
ListModelMixin,查询所有写了一个方法  list,代码就是 跟咱们之前写查询所有的 get  方法内容一样
UpdateModelMixin  修改一个写了一个方法  update,代码就是 跟咱们之前写更新一条数据的put  方法内容一样

为什么把他们单独写成五个,而不是两个

因为后期有可能只使用其中一个方法,直接调用即可,不用在写

代码展示:

class PublishView(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = Publish.objects.all()  # 类只要加载,就会执行,查了所有数据,不能以它为准
    serializer_class = PublishSerializer

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

    def post(self, request):
        # return  self.create(request) # 一定不要忘了return
        return super().create(request)  # 一定不要忘了return


class PublishDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    serializer_class = PublishSerializer
    queryset = Publish.objects.all()

    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)