系列文章目录
drf
第一章 django web开发模式、api接口、api接口测试工具、restful规范、序列化反序列化、drf安装使用
第二章 drf的使用、APIView源码分析、Request源码分析、Serializer的序列化
文章目录
一、drf的使用
1.drf容器注册
由于drf实质上是一个app,所以在使用前需要对其进行app注册
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.Qpp01Config',
'rest_framework', # 注册drf容器
]
2.模型层建立模型
如下创建对应的模型
class Book(models.Model):
pname = models.CharField(max_length=20)
price = models.DecimalField(max_digits=5,decimal_places=2)
author = models.CharField(max_length=20)
press = models.CharField(max_length=20)
3.序列化类创建
创建一个serializer.py文件,名字可以自行设定
serializer类中的属性要与模型层的属性对应,可以只对应部分,对应多少序列化时便序列化多少属性
from rest_framework import serializers
class BookSerializer(serializers.Serializer):
pname = serializers.CharField(max_length=20)
price = serializers.DecimalField(max_digits=5, decimal_places=2)
author = serializers.CharField(max_length=20)
press = serializers.CharField(max_length=20)
4.视图函数创建
views.py
from rest_framework import views
from rest_framework.response import Response
from rest_framework.request import Request
from .models import Book
from .serializer import BookSerializer
class BookApiView(views.APIView):
def get(self,request):
books = Book.objects.all()
bookSerializer = BookSerializer(instance=books, many=True)
return Response(bookSerializer.data)
5.开启路由
urls.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('api/book/', views.BookApiView.as_view()),
]
二、APIView源码分析
def as_view(cls, **initkwargs):
if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
def force_evaluation():
raise RuntimeError(
'Do not evaluate the `.queryset` attribute directly, '
'as the result will be cached and reused between requests. '
'Use `.all()` or call `.get_queryset()` instead.'
)
cls.queryset._fetch_all = force_evaluation
view = super().as_view(**initkwargs) #此处APIView继承了django的view的as_view
view.cls = cls
view.initkwargs = initkwargs
return csrf_exempt(view)
# 项目启动后as_view()优先执行,返回csrf_exempt(view)
def csrf_exempt(view_func):
def wrapped_view(*args, **kwargs):
return view_func(*args, **kwargs)
wrapped_view.csrf_exempt = True
return wraps(view_func)(wrapped_view)
## csrf_exempt(view)运行返回wraps(view_func)(wrapped_view)
def wraps(wrapped,
assigned = WRAPPER_ASSIGNMENTS,
updated = WRAPPER_UPDATES):
return partial(update_wrapper, wrapped=wrapped,
assigned=assigned, updated=updated)
'''
wraps(view_func)(wrapped_view)运行后返回partial为
partial(wrapped_view, wrapped=view_func,assigned=assigned, updated=updated)
'''
# 当请求接入时触发dispatch函数
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
# 此处将django原来的request封装成了新的request
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
# 此处有三重验证:权限、认证、频率
self.initial(request, *args, **kwargs)
# Get the appropriate handler method
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进行封装,变为了drf自己的response
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
三、Request源码分析
class Request:
"""
Wrapper allowing to enhance a standard `HttpRequest` instance.
Kwargs:
- request(HttpRequest). The original request instance.
- parsers(list/tuple). The parsers to use for parsing the
request content.
- authenticators(list/tuple). The authenticators used to try
authenticating the request's user.
"""
def __init__(self, request, parsers=None, authenticators=None,
negotiator=None, parser_context=None):
assert isinstance(request, HttpRequest), (
.format(request.__class__.__module__, request.__class__.__name__)
)
#将原来的request放入_request中
self._request = request
# 从django的request中获取数据到drf的request
if self.parser_context is None:
self.parser_context = {}
self.parser_context['request'] = self
self.parser_context['encoding'] = request.encoding or settings.DEFAULT_CHARSET
force_user = getattr(request, '_force_auth_user', None)
force_token = getattr(request, '_force_auth_token', None)
四、serializer的序列化
创建一个serializer.py文件,名字可以自行设定
serializer类中的属性要与模型层的属性对应,可以只对应部分,对应多少序列化时便序列化多少属性
from rest_framework import serializers
class BookSerializer(serializers.Serializer):
pname = serializers.CharField(max_length=20)
price = serializers.DecimalField(max_digits=5, decimal_places=2)
author = serializers.CharField(max_length=20)
press = serializers.CharField(max_length=20)
序列化:
from django.shortcuts import render
from rest_framework import views
from rest_framework.response import Response
from rest_framework.request import Request
from .models import Book
from .serializer import BookSerializer
# Create your views here.
class BookApiView(views.APIView):
def get(self,request):
#查询数据
books = Book.objects.all()
#将数据序列化
bookSerializer = BookSerializer(instance=books, many=True)
return Response(bookSerializer.data)