DRF从入门到入土(二)
一、APIView基本使用
使用view+JsonResponse获取所有图书接口
安装drf: pip3 install djangorestframework
settings.py注册app:
'rest_framework'
models.py
from django.db import models
class Book(models.Model):
name = models.CharField(max_length=32, verbose_name='书籍名')
price = models.CharField(max_length=32, verbose_name='书籍价格')
publish = models.CharField(max_length=32, verbose_name='书籍出版社')
views.py
from django.views import View
from .models import Book
创建视图类,继承View获取所有图书的接口
class BookView(View):
def get(self, request):
book_list = Book.objects.all()
obj_list = []
for book in book_list:
obj_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
return JsonResponse(obj_list, safe=False, json_dumps_params={'ensure_ascii': False})
页面展示

使用APIView+drf的Response获取所有图书接口
from django.views import View
from .models import Book
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
class BookView(APIView):
def get(self, request):
book_list = Book.objects.all()
obj_list = []
for book in book_list:
obj_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
return Response(obj_list)
Postman工具测试成功

浏览器访问报错

修改setting.py配置文件

重新使用浏览器访问

二、APIView源码分析
-路由配置跟之前继承View是一样的----》找视图类的as_view---》【APIView的as_view】
@classmethod
def as_view(cls, **initkwargs):
view = super().as_view(**initkwargs)
'''
# 从此以后,所有的请求都没有csrf的校验了
# 在函数上加装饰器
@csrf_exempt
def index(request):
pass
本质等同于 index=csrf_exempt(index)
'''
return csrf_exempt(view)
-请求来了,路由匹配成功会执行 View类的的as_view类方法内的view闭包函数(但是没有了csrf认证),
-真正的执行,执行self.dispatch---->APIView的dispatch 【这是重点】
def dispatch(self, request, *args, **kwargs):
request = self.initialize_request(request, *args, **kwargs)
self.request = request
try:
self.initial(request, *args, **kwargs)
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
except Exception as exc:
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
1 只要继承APIView都没有csrf的认证了
2 以后视图类中使用的request对象,已经变成了drf提供的Request类的对象了
3 执行视图类的方法之前,执行了3大认证(认证,权限,频率)
4 在执行三大认证和视图类的方法过程中只要报错,都会被捕获处理
三、Request源码分析
-原生djagno 的request是这个类的对象:django.core.handlers.wsgi.WSGIRequest
-drf的request是这个类的对象:rest_framework.request.Request
-用起来,像之前一样
print(request.method)
print(request.path)
print(request.GET)
print(request.POST)
-类中有个魔法方法:__getattr__ 对象.属性,属性不存在会触发它的执行
def __getattr__(self, attr):
try:
return getattr(self._request, attr)
except AttributeError:
return self.__getattribute__(attr)
-以后用的所有属性或方法,直接用就可以了---》(通过反射去原来的request中取的)
-新的request内部有个老的request,就是 request._request
-data 是个方法,被property装饰了,变成了数据属性用
-以后body体中提交的数据,都从这里取(request.POST)
-urlencoded,form-data:提交的数据在request.POST中
-json格式提交的数据,在requets.POST中没有,它在request.body中
-现在无论那种格式,都从request.data中取
-query_params:get请求提交的参数,等同于request._request.GET 或 request.GET
-其他:取文件也是从request.FILES中取,跟之前一样
1 在类中只要以__开头,__结尾的都称之为魔法方法
2 这种方法不需要手动调用,某种情况会自动触发
3 你学过的: __init__,__str__,__call__,......
四、序列化组件介绍
-使用for循环,列表套字典拼接的
五、序列化组件基本使用
定义一个序列化类
from rest_framework import serializers
class BookSerializer(serializers.Serializer):
name = serializers.CharField()
price = serializers.CharField()
publish = serializers.CharField()
使用序列化类,序列化多条数据
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import BookSerializer
class BookView(APIView):
def get(self, request):
book_list = Book.objects.all()
ser = BookSerializer(instance=book_list, many=True)
return Response(ser.data)
结果验证


使用序列化类,序列化单条数据
路由层urls.py
from django.contrib import admin
from django.urls import path
from app01.views import BookView, BookDetailView
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', BookView.as_view()),
path('books/<int:pk>/', BookDetailView.as_view())
]
视图层views.py
class BookDetailView(APIView):
def get(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book)
return Response(ser.data)
结果验证

六、反序列化组件基本使用
反序列化之新增数据(需要进行数据校验)
视图类
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import BookSerializer
class BookView(APIView):
def post(self, request):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
序列化类
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.Serializer):
name = serializers.CharField()
price = serializers.CharField()
publish = serializers.CharField()
def create(self, validated_data):
add = Book.objects.create(**validated_data)
return add
结果验证


反序列化之修改数据
视图类
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import BookSerializer
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)
序列化类
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.Serializer):
name = serializers.CharField()
price = serializers.CharField()
publish = serializers.CharField()
def update(self, instance, validated_data):
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
instance.publish = validated_data.get('publish')
instance.save()
return instance
结果验证


反序列化之删除数据
视图类
class BookDetailView(APIView):
def delete(self, request, pk):
Book.objects.filter(pk=pk).delete()
return Response()
结果验证


七、HTTP各版本区别
HTTP协议
超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。HTTP使用的默认端口号是80端口
HTTPS使用的默认端口是443端口
HTTP协议发展
http协议目前有4个版本,其中1.0和1.1版本在互联网上被广泛使用,2.0版本目前应用很少,是下一代的http协议。
http/0.9版本:1991年,原型版本,功能简陋,只有一个命令GET,服务器只能回应HTML格式字符串,该版本已过时。
http/1.0版本:1996年5月,支持cache、MIME、method等。
http/1.1版本:1997年1月,默认建立持久连接,并能很好地配合代理服务器工作。还支持以管道方式在同时发送多个请求,以便降低线路负载,提高传输速度。
http/2 版本:2015年5月作为互联网标准正式发布,头部信息和数据体都是二进制,引入头信息压缩机制等。
HTTP1.0版本
任何格式的内容都可以发送,这使得互联网不仅可以传输文字,还能传输图像、视频、二进制等文件。
除了GET命令,还引入了POST命令和HEAD命令。
http请求和回应的格式改变,除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据。
头信息是 ASCII码,而后面数据可为任何格式。服务器回应时会告诉客户端,数据是什么格式,即Content-Type字段的作用。这些数据类型总称为MIME即多用途互联网邮件扩展,每个值包括一级类型和二级类型,预定义的类型,也可自定义类型,常见Content-Type值:text/xml image/jpeg audio/mp3
每个TCP连接只能发送一个请求,发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接
关于HTTP消息头
HTTP消息头是在客户端请求(Request)或服务器响应(Response)时传递的。以明文的字符串格式传送,是以冒号分隔的键/值对,如:Accept-Charset: utf-8,每一个消息头最后以回车符(CR)和换行符(LF)结尾。HTTP消息头结束后,会用一个空白的字段来标识,这样就会出现两个连续的CR-LF。
HTTP1.1版本
引入了持久连接( persistent connection),即TCP连接默认不关闭,可以被多个请求复用,默认Connection: keep-alive,如果响应方不支持keep-alive,则修改为Connection: close
引入了管道机制(pipelining),即在同一个TCP连接里,客户端可以同时发送多个请求(大多数浏览器允许同时建立6个持久连接引入了管道机制),进一步改进了HTTP协议的效率。
新增方法:PUT、 PATCH、 OPTIONS、 DELETE。
http协议不带有状态,每次请求都必须附上所有信息。请求的很多字段都是重复的,浪费带宽,影响速度。
传输数据是明文,客户端和服务器端都无法验证对方的身份,无法保证数据的安全性。
header头部数据太长。
每次传输还是要重新连接。
server不能主动push。
1.1版本允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应,可能会造成Head-of-line blocking(队头阻塞)的问题。
HTTP2.x版本
http/2发布于2015年,目前应用还比较少,该版本主要有如下特点:
http/2是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为"帧"(frame):头信息帧和数据帧。
复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,且不用按顺序一一对应,避免了队头堵塞的问题。此双向的实时通信称为多工(Multiplexing)。
HTTP/2 允许服务器未经请求,主动向客户端发送资源,即服务器推送。
引入头信息压缩机制(header compression),头信息使用gzip或compress压缩后再发送;客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,不发送同样字段,只发送索引号,提高速度。
八、自主练习
1 继承apiview写5个接口
from .models import Book
from rest_framework.views import APIView
from django.http import JsonResponse
class BookView(APIView):
def get(self, request):
books = []
book_list = Book.objects.all()
for book in book_list:
books.append({'name': book.name, 'price': book.price, 'publish': book.publish})
return JsonResponse(books, safe=False, json_dumps_params={'ensure_ascii': False})
def post(self, request):
name = request.data.get('name')
price = request.data.get('price')
publish = request.data.get('publish')
book = Book.objects.create(name=name, price=price, publish=publish)
return JsonResponse({'info': '新增成功'})
class BookDetailView(APIView):
def get(self, request, pk):
book = Book.objects.all().filter(pk=pk).first()
return JsonResponse({'id': book.id, 'name': book.name, 'price': book.price, 'publish': book.publish})
def delete(self, request, pk):
Book.objects.all().filter(pk=pk).delete()
return JsonResponse({'info': '删除成功'})
def put(self, request, pk):
book = Book.objects.all().filter(pk=pk).first()
book.name = request.data.get('name')
book.price = request.data.get('price')
book.publish = request.data.get('publish')
book.save()
return JsonResponse({'info': '修改成功'})





【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)