drf请求
1.1drf请求之Request类
# from rest_framework.request import Request
# 1 以后视图类的方法中的request都是这个类的对象
# 2 以后使用request.data 取请求体中的数据
# 3 以后使用request.query_params 取请参数中的数据
# 4 以后其他属性,用起来跟之前一样--->重要
为什么我还可以直接使用request.method方法?
当我request.method 的时候--->实际上底层会反射出来 request._request.'method'
-这个类from rest_framework.request import Request没有method,他会触发这个类的__getattr__
# 5 FILES 用起来跟之前一样,前端传入的文件在里面
1.2控制前端请求编码格式
针对前端传入的编码:urlencoded、form-data、josn
# 某些接口只做josn格式的接收、某些接口只做urlencoded格式的接收、某些接口只做form-data格式的接收,该怎么去做?这时候就用到了,控制前端传的编码格式了
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
JSONParser:只能传json
FormParser:只能传urlencoded
MultiPartParser:只能传form-data
方法一:# 在视图函数内局部使用,局部使用优先与全部使用
class BookView(APIView):
parser_classes = [FormParser] # 设置这个是视图类只能接收urlencoded格式的数据
方法二:全局生效----->所有接口只能支持一种或两种数据格式
在配置文件中添加配置
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
# 'rest_framework.parsers.MultiPartParser'
# 所有接口仅支持josn跟urlencoded
]
}
方法三:全局使用以后局部限制------>只需要在视图类中添加即可
class BookView(APIView): # 全局如果用了,局部这样配,优先用局部的,也就是这个类管理的接口,只能接收form-data格式
parser_classes = [MultiPartParser]
我们什么都没配置为什么还能接收三种格式的数据?
因为在drf内部的配置文件中为我们做了这些事情
drf响应
2.1drf之Response对象源码
模块:# from rest_framework.response import Response
在Response内部的__init__的形参中有几个参数:
data:响应体中的数据
status:响应状态码 ,注意响应状态码千万不能写成1XX
template_name:模版名称,默认是:rest_framework/api.html 了解,可以定制自己返回的页面样子
headers:响应头
content_type:响应的数据格式
补充:
res = Response(data={}, status=200, headers={"xxxx": "yyyyy"})
print(res.data) # 获取到响应体中的数据
res.headers # headers的数据,因为源码内部没有写
res["xxxx"] # 获取响应头的数据
res.has_header('zzz')# 用于检查请求头中是否存在某个特定的头部字段。这个方法返回一个布尔值
return res
drf之响应格式
# 响应有编码格式:默认支持json和text/html(浏览器)
# 局部使用:
如果我只想支持josn
from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer
class BookView(APIView): # 这个视图类只支持josn
renderer_classes = [JSONRenderer]
# 全局使用:
在配置文件中配置##局部禁用---》全局已经配置了---》局部想用浏览器的样子
class BookView(APIView):
renderer_classes = [BrowsableAPIRenderer]
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
}
##局部禁用--->全局已经配置了--->局部想用浏览器的样子
class BookView(APIView):
renderer_classes = [BrowsableAPIRenderer]
解析和响应总结;
解析:默认三种都可以解析
局部限制:parser_classes
全局限制:配置文件
全局限制加局部限制:在视图类中写parser_classes会优先局部的
响应:默认两种都可以响应
局部限制:renderer_classes
全局限制:配置文件
全局限制加局部限制:在视图类中写renderer_classes会优先局部的
两个视图基类
继承自己写的GenericAPIView(只要跟数据库打交道)
视图层
class GenericAPIView(APIView):
queryset = None
serializer_class = None
def get_queryset(self):
queryset = self.queryset
return queryset.all() # 要以这个地方的查询为主
# models.Book.objects.all()
def get_object(self, pk):
res = self.get_queryset()
return res.filter(pk=pk).first()
# models.Book.objects.all().filter(pk=pk).first()
def get_serializer(self, *args, **kwargs):
return self.serializer_class(*args, **kwargs)
class BookThreeView(GenericAPIView):
queryset = models.Book.objects.all()
# 类只要加载,就会执行,查了所有数据,不能以它为准
serializer_class = BookSerializer
def get(self, request):
book_obj = self.get_queryset()
book = self.get_serializer(book_obj, many=True)
return Response(book.data)
def post(self, request):
book_obj = self.get_serializer(data=request.data)
# 方法一
# if book_obj.is_valid():
# book_obj.save()
# return Response(book_obj.data)
# 方法二
book_obj.is_valid(raise_exception=True)
book_obj.save()
return Response(book_obj.data)
class BookThreeDetailView(GenericAPIView):
queryset = models.Book.objects.all()
serializer_class = BookSerializer
def get(self, request, pk):
book_obj = self.get_object(pk)
book = self.get_serializer(book_obj)
return Response(book.data)
def put(self, request, pk):
book_obj = self.get_object(pk)
book = self.get_serializer(book_obj, data=request.data)
book.is_valid(raise_exception=True)
book.save()
return Response(book.data)
def delete(self, request, pk):
self.get_object(pk).delete()
return Response("")
序列化层
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = ["book_name", "book_price", "publish_dic", "author_list", "publish", "authors"]
extra_kwargs = {
# "book_name": {"max_length": 8, "min_length": 2},
# "book_price": {"max_value": 1000, "min_length": 20},
"publish": {"write_only": True},
"authors": {"write_only": True},
}
publish_dic = serializers.DictField(read_only=True)
author_list = serializers.ListField(read_only=True)
路由层
urlpatterns = [
path('booksthree/', BookThreeView.as_view()),
path('booksthree/<int:pk>', BookThreeDetailView.as_view()),
]
继承drf中的GenericAPIView写的
from rest_framework.generics import GenericAPIView
class BookTwoView(GenericAPIView):
queryset = models.Book.objects.all()
serializer_class = BookSerializer
def get(self, request):
book_obj = self.get_queryset()
book = self.get_serializer(book_obj, many=True)
return Response(book.data)
def post(self, request):
book = self.get_serializer(data=request.data)
if book.is_valid():
book.save()
return Response({"code": 100, "msg": book.data})
else:
return Response({"code": 101, "msg": book.errors})
class AddTwoBookView(GenericAPIView):
queryset = models.Book.objects
serializer_class = BookSerializer
def put(self, request):
book_obj = self.get_object()
book = self.get_serializer(book_obj)
if book.is_valid():
book.save()
return Response({"code": 200, "msg": book.data})
else:
return Response({"code": 101, "msg": book.errors})
def delete(self, request, pk):
self.get_object().delete()
return Response({"code": 100, "msg": "删除成功"})
GenericAPIView 有类属性和方法
重要属性:
queryset:放的是表中查询出来的所有数据
serializer_class:序列化的类
重要方法:
get_queryset:要序列化的所有数据,是QuerySet对象
get_serializer :序列化类
get_object:修改、查询涉及到单条数据
了解属性:
lookup_field = "pk":路由使用转换器,转换出来的参数,查询单条的时候要用到,如果改了,对应的路由也要改
filter_backends:过滤功能
pagination_class:分页功能
了解方法:
get_serializer_class:后期可能会重写此方法,指定某些方法使用不同的序列化类
filter_queryset:可以对查询结果进行进一步的筛选和过滤
5个视图扩展类(不是视图类-->先继承GenericAPIView)
ListModelMixin--->查询所有,写了一个方法--->返回list,代码就是 跟咱们之前写获取单条get方法内容一样
CreateModelMixin --->新增一条,写了一个方法---->返回create,代码就是 跟咱们之前写获取单条post方法内容一样
RetrieveModelMixin --->查询一条,写了一个方法--->返回retrieve,代码就是 跟咱们之前写获取单条get方法内容一样
UpdateModelMixin --->修改一条,写了一个方法--->返回updata,代码就是 跟咱们之前写获取单条put方法内容一样
DestroyModelMixin --->删除一条,写了一个方法---->返回destroy,代码就是 跟咱们之前写获取单条delete方法内容一样
# 为什么写5个,不写俩?
因为后期不一定 5个接口都写
视图类
class BookThreeView(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = models.Book.objects.all()
serializer_class = BookSerializer
def get(self, request):
return self.list(request)
def post(self, request):
return self.create(request)
class BookThreeDetailView(GenericAPIView, DestroyModelMixin, UpdateModelMixin, RetrieveModelMixin):
queryset = models.Book.objects.all()
serializer_class = BookSerializer
def get(self, request):
return self.retrieve(request)
def put(self, request):
return self.update(request)
def delete(self, request):
return self.destroy(request)
"只有视图类在变其他都不会变"