drf请求、响应编码格式、视图类、视图扩展类

drf请求之Request类

1、新的request视图层的方法中的request都是这个类(from rest_framework.request import Request)的对象

2、使用request.data 取请求体中的数据(之前的Json传值request.body)

3、使用request.query_params 取请求参数中的数据

4、其他属性,用起来和之前一样

    -request.method 的时候---》实际上 request._request.'method'---》反射出来的

-这个类from rest_framework.request import Request没有method,他会触发这个类的__getattr__---》

5 、FILES 用起来跟之前一样,前端传入的文件在里面

了解:

视图类方法中,self是咱们写的视图类 对象,self.request是新的request

控制前端请求的编码格式

前端传入的编码:urlencoded、json、form-data

某些接口只能接收到某种编码的处理方式

from rest_framework.parsers import JSONParser, FormParser, MultiPartParser

方式一:

   JSONParser:解析json格式
   FormParser:urlencoded
   MultiPartParser:form-data

  局部使用—在视图类上配置,且优先使用他

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

方式二:

  全局生效,在配置文件中写,所有接口都支持某一种或者某几种

 

全局使用后,再局部使用,只需要在视图类上加上即可,因为优先使用视图类

# 全局如果用了,局部这样配,优先用局部的,也就是这个类管理的接口,只能接收form-data格式

class BookView(APIView): 
    parser_classes = [MultiPartParser]

drf自己有默认配置,默认配置就是支持三种,所以我们即使没有配置,也可以使用三种。

print(self.parser_classes)  #打印接收格式
 
当输入的编码格式不匹配时,会显示如下错误

 

 

drf之响应

drf之Response对象源码

from rest_framework.response import Response

Response
 __init__ 中需要传这几个参数,不传也可以
data=None    # 字符串,列表,字典----》放在了响应 体 中 ---》第一个参数是它

status = None    #http响应状态码,默认是200,可以改成3xx、4xx、5xx,不能改为1xx,因为1xx请求正在处理中,执行代码后会崩掉

content_type=None     #响应编码格式(这个不用管,用浏览器访问就是text/html,用postman就是:json格式)

template_name=None  #模板名字 默认是:rest_framework/api.html 可以定制自己返回页面的样式

 

通过res.data可以取到当时放的data

res=Response(data={},status=500,headers={'xxx':'yyy'}) #响应状态码是500,请求头是{'xxx':'yyy'}
print(res.data)   #{}
return res

 

取当时放的响应头:

res.headers 拿不到数据,可以通过下面的方式或得到
print(res['xxx'])   #yyy

print(res.has_header('zzz'))  #False 这里是判断请求头是否是zzz

源码:

原生django怎么给响应头写入数据

直接在HttpResponse响应对象中添加键值对

 JsonResponse也是同理,在响应对象中添加键值对

 

drf之响应格式

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

from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer

局部使用:

class BookView(APIView):

  renderer_classes = [BrowsableAPIRenderer]   #只支持浏览器格式

全局使用:

 局部禁用:

  当全局已经配置,局部想要限制的话,可以直接局部限制,也就是上述的局部使用

如果不配置:

  有默认格式,解析方面:三种编码都能解析,响应方面:浏览器访问看到浏览器的样子,postman访问看到json格式

 注意:使用 BrowsableAPIRenderer要记得注册,这样才会显示页面

 不注册就会报错

基于API写接口

from rest_framework.views import APIView

视图类

from rest_framework.views import APIView
from .models import Book
from .serializer import Bookserializer
class BookView(APIView):
    def get(self,request):
        book_list = Book.objects.all()
        rse = Bookserializer(book_list,many=True)
        return Response({'code':111,'msg':'查询成功','defult':rse.data})

    def post(self,request):
        rse = Bookserializer(data=request.data)
        if rse.is_valid():
            rse.save()
            return Response({'code':200,'msg':'添加成功','defult':rse.data})
        else:
            return Response({'code':201,'msg':'添加失败','defult':rse.errors})

class BookDetialView(APIView):
    def get(self,request,pk):
        book = Book.objects.filter(pk=pk).first()
        res = Bookserializer(book)
        return Response({'code': 111, 'msg': '查询成功', 'defult': res.data})

    def put(self,request,pk):
        book = Book.objects.filter(pk=pk).first()
        res = Bookserializer(instance=book,data=request.data)
        if res.is_valid():
            res.save()
            return Response({'code':200,'msg':'修改成功','defult':res.data})
        else:
            return Response({'code': 201, 'msg': '添加失败', 'defult': res.errors})

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

序列化类

from .models import Book
from rest_framework import serializers

class Bookserializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['name','price','publish','author','publish_detial','author_dic']
        extra_kwargs ={
            'publish': {'write_only': True},
            'author': {'write_only': True}
        }  #反序列化,写入的数据




    #序列化,显示出去的数据,在模型层的数据
    publish_detial = serializers.DictField(read_only=True)
    author_dic = serializers.ListField(read_only=True)

模型层

from django.db import models

# Create your models here.

class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.IntegerField()
    publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
    author = models.ManyToManyField(to='Author')

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

    def author_dic(self):
        #作者表是一个列表
        l = []
        for author in self.author.all():
            l.append({'name':author.name,'age':author.age,'sex':author.get_sex_display()})
        return l


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

class Author(models.Model):
    sex_choice =[(1,''),(2,''),(3,'未知')]
    name = models.CharField(max_length=32)
    age = models.IntegerField(default=18)
    sex = models.IntegerField(choices=sex_choice,default=1)

 

基于GenericAPIView

视图类封装

GenericAPIView 有类属性和方法

from rest_framework.generics import GenericAPIView

重要属性: 

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

重要方法:    

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

了解属性:

    -lookup_field = 'pk'   路由使用转换器,转换出来的参数,查询单条要用到,如果改了,路由对应也要修改,但是一般不改

    -filter_backends:后面详细讲 过滤 功能
    -pagination_class :后面详细讲 分页

了解方法:    

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

以下代码为视图类:

#封装
class GenericAPIView(APIView):
    queryset = None
    serializer_class = None

    # 查找全部
    def get_queryset(self):
        return self.queryset.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()
class BookView(GenericAPIView):
    queryset = Book.objects   #即使这里加了all,后续查询所以也需要加,所以在封装的get_queryset中有all
    serializer_class = Bookserializer
    def get(self,request):
        query_list = self.get_queryset()
        res = self.serializer_class(query_list,many=True)
        return Response({'code': 111, 'msg': '查询成功', 'defult': res.data})


    def post(self,request):
        res = self.serializer_class(data=request.data)
        if res.is_valid():
            res.save()
            return Response({'code': 200, 'msg': '添加成功', 'defult': res.data})
        else:
                return Response({'code':201,'msg':'添加失败','defult':res.errors})


class BookDetialView(GenericAPIView):
    queryset = Book.objects  # 即使这里加了all,后续查询所以也需要加,所以在封装的get_queryset中有all
    serializer_class = Bookserializer
    def get(self,request,pk):
        obj = self.get_object(pk)
        res = self.serializer_class(obj)
        return Response({'code': 111, 'msg': '查询成功', 'defult': res.data})

    def put(self,request,pk):
        obj = self.get_object(pk)
        res = self.serializer_class(instance=obj,data=request.data)
        if res.is_valid():
            res.save()
            return Response({'code': 200, 'msg': '修改成功', 'defult': res.data})
        else:
            return Response({'code': 201, 'msg': '修改失败', 'defult': res.errors})


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

关于一些错误

错误一:

  一定要用在数据的时候再查:

def get_queryset(self):
    return self.queryset.all()

  

5个视图扩展类(不是视图类--》先继承GenericAPIView)

一定要先继承GenericAPIView,

from rest_framework.generics import GenericAPIView
from rest_framework.mixins import RetrieveModelMixin, CreateModelMixin, DestroyModelMixin, ListModelMixin,UpdateModelMixin

RetrieveModelMixin:查询一条

  retrieve---》代码就是和之前写获取单条get方法内容一样

CreateModelMixin : 新增一条

  create---》代码就是和之前写新增一条 post  方法内容一样

DestroyModelMixin:删除一条

  destroy---》代码就是和之前写删除一条 delete  方法内容一样

ListModelMixin:查询所有

  list---》代码就是和之前写删除一条 get  方法内容一样

UpdateModelMixin

  update---》代码就是和之前写删除一条put  方法内容一样

 

#写五个接口,而不封装成两个接口的原因是因为后期不一定5个接口都写,可能只使用其中几个

以下代码为视图类

from rest_framework.mixins import RetrieveModelMixin, CreateModelMixin, DestroyModelMixin, ListModelMixin, \
    UpdateModelMixin
from rest_framework.generics import GenericAPIView


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

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

    def post(self, request, *args, **kwargs):
        return self.create(request)


class BookDetialView(GenericAPIView, RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin):
    queryset = Book.objects.all()
    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.delete(request, pk)

 

补充:

关于模型的类似于性别这种以数字代替文字,但读取时要以文字读取出来

 

posted @ 2023-09-04 15:59  别管鱼油我了  阅读(41)  评论(0编辑  收藏  举报