- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
我们还是在models模型层中创建一个book类
里面包含 name/price字段
我们就使用django自带的sqlite数据库即可
'modles.py'
from django.db import models
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32)
'views'
from django.shortcuts import render
from rest_framework.views import APIView # 导入APiView
from django.http import JsonResponse
from app01 import models
class BookView(APIView): # 继承APIView类
def get(self, request):
book_queryset = models.Book.objects.all()
book_list = []
for book_obj in book_queryset: book_list.append({'name':book_obj.name,'price':book_obj.price})
return JsonResponse(book_list,safe=False)
# 因为在返回列表格式数据的时候会出现问题,需要将safe=False
'urls'
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book/api/v1/',views.BookView.as_view()),
]
与JsonResponse基本一致,只是在返回数据时,不需要进行safe=False的操作
def get(self,request):
book_queryset = models.Book.objects.all()
book_list = []
for book_obj in book_queryset:
book_list.append({'name':book_obj.name,'price':book_obj.price})
return Response(book_list)
我们接下来分析以下APIView和View到底有什么区别?
首先是APIView的执行流程:
路由层:path('book/api/v1/',views.BookView.as_view()),
请求来了,执行views.BookView.as_view()()
'as_view()是APIView中的方法,并不是View的了!'
# 调用父类的as_view()方法,APIView继承的是View
view = super().as_view(**initkwargs)
# 拿到父类中的闭包函数view
as_view() 方法 返回了 >>>> return csrf_exempt(view)
# csrf_exempt 排除所有csrf的认证
# 相当于在所有的方法上面加了这个装饰器
路由匹配成功,执行 csrf_exempt(view)(requets)
相当于回到了View类中,执行闭包函数view,返回的是
return self.dispatch(request, *args, **kwargs)
这个self就是我们视图函数中编写的BookView类产生的对象
所以执行对象.dispatch,因为这个BookView继承了APIView
正好在APIView中也有dispatch方法
def dispatch(self, request, *args, **kwargs):
# request是django原生的request,老的request
request = self.initialize_request(request, *args, **kwargs)
self.request = request
# 把老的request包装成了新的request,这个是drf提供的Request类的对象
try:
# 执行了三大认证(认证,频率,权限)使用新的request
self.initial(request, *args, **kwargs)
接下来跟CBV源码都一样了
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
# 将新的request传入,视图类中的get的request也是新的request
response = handler(request, *args, **kwargs)
except Exception as exc:
# 在执行3大认证和视图类中方法的过程中,如果出了异常,都能捕获到---》全局异常捕获
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
# 总结
1 去除了所有的csrf
2 包装了新的request,以后在视图类中用的request是新的request Request类的对象,不是原生的了
-原生的在:新的requets._request
3 在执行视图类的方法之前,执行了3大认证
4 如果在3大认证或视图函数方法执行过程中出了错,会有异常捕获>>>全局异常捕获
5 以后视图类方法中的request都是新的了
在Request类中有__getattr__魔法方法
如果我们使用新的request.method方法就会触发Request中的__getattr__方法
def __getattr__(self, attr):
try:
return getattr(self._request, attr) # 会从老的request中获取method方法
except AttributeError:
return self.__getattribute__(attr)
-request.data--->这是个方法,包装成了数据属性
-以后无论post,put 在body中提交的数据,都从request.data中取,取出来就是字典
-无论是那种编码格式
-request.query_params--->这是个方法,包装成了数据属性
-get请求携带的参数,以后从这里面取
-query_params:查询参数--->restful规范请求地址中带查询参数
-request.FILES--->这是个方法,包装成了数据属性
-前端提交过来的文件,从这里取
它们都携带了@property装饰器,将方法伪装成了属性 。
# Request类总结
-1 新的request用起来,跟之前一模一样,因为新的取不到,会取老的__getattr__
-2 request.data 无论什么编码,什么请求方式,只要是body中的数据,就从这里取(字典格式)
-3 request.query_params 就是原来的request._request.GET
-4 上传的文件从request.FILES中取
我们在编写接口时,经常需要使用到序列化和反序列化
并且在反序列化过程中需要进行数据校验
drf中直接提供了固定的写法,我们只需要按照固定写法编写即可完成上述需求
drf提供了两个类 Serializer/ModelSerializer
以后我们只需要编写自己的类,继承drf提供的序列化类
使用其中的某些方法即可
**serializer.py >>> BookSerializer类 。
from rest_framework import serializers
class BookSerializer(serializers.Serializer):
name = serializers.CharField() # 只需要填写需要序列化的字段即可
price = serializers.CharField()
views视图 >>> BookView类 。
def get(self,request):
book_queryset = models.Book.objects.all()
serializer_obj = serializer.BookSerializer(instance=book_queryset,many=True)
# instance 参数是指定需要序列化的对象,
# many 参数是如果有多个对象就需要将many参数改为True,默认为False
return Response(serializer_obj.data)
urls路由层 >>> urlpatterns 。
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book/api/v1/',views.BookView.as_view()),
]
**serializer.py >>> BookSerializer类 。
from rest_framework import serializers
class BookSerializer(serializers.Serializer):
name = serializers.CharField() # 只需要填写需要序列化的字段即可
price = serializers.CharField()
# 新增数据需要我们自己编写create方法来进行保存
def create(self, validated_data):
# validated_data >> 校验完成的数据
book_obj = models.Book.objects.create(**validated_data)
return book_obj
views视图 >>> BookView类 。
def post(self,request):
# 因为是新增数据我们需要将前端传递来的数据反序列化
serializer_obj = serializer.BookSerializer(data=request.data)
if serializer_obj.is_valid(): # 校验数据是否合法
# 合法的数据通过ser_obj点save方法自动调用序列化文件中的create方法
serializer_obj.save()
return Response({"code":100,"msg":'新增成功','result':serializer_obj.data})
else:
return Response({"code":101,'msg':serializer_obj.errors})
urls路由层 >>> urlpatterns 。
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book/api/v1/',views.BookView.as_view()),
]
**serializer.py >>> BookSerializer类 。
from rest_framework import serializers
class BookSerializer(serializers.Serializer):
name = serializers.CharField() # 只需要填写需要序列化的字段即可
price = serializers.CharField()
views视图 >>> BookDetailView类 。
class BookDetailView(APIView):
def get(self, request, pk):
book_obj = models.Book.objects.filter(pk=pk).first()
serializer_obj = serializer.BookSerializer(instance=book_obj)
return Response(serializer_obj.data)
urls路由层 >>> urlpatterns 。
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book/api/v1/',views.BookView.as_view()),
path('book/api/v1/<int:pk>/',views.BookDetailView.as_view()),
]
**serializer.py >>> BookSerializer类 。
class BookSerializer(serializers.Serializer):
name = serializers.CharField()
price = serializers.CharField()
def create(self, validated_data):
# validated_data >> 校验完成的数据
# name = validated_data.get('name')
# price = validated_data.get('price')
book_obj = models.Book.objects.create(**validated_data)
return book_obj
def update(self, instance, validated_data):
# instance就是需要序列化的数据对象
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
instance.save()
return instance # 返回序列化数据对象
views视图 >>> BookDetailView类 。
def put(self,request,pk):
book_obj = models.Book.objects.filter(pk=pk).first()
serializer_obj = serializer.BookSerializer(instance=book_obj,data=request.data)
if serializer_obj.is_valid():
serializer_obj.save() # 会自动调用update方法进行修改操作
return Response({"code": 103, "msg": '修改成功', 'result': serializer_obj.data})
else:
return Response({"code": 104, 'msg': serializer_obj.errors})
urls路由层 >>> urlpatterns 。
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book/api/v1/',views.BookView.as_view()),
path('book/api/v1/<int:pk>/',views.BookDetailView.as_view()),
]
views视图 >>> BookDetailView类 。
class BookDetailView(APIView):
def delete(self, requset, pk):
Book.objects.filter(pk=pk).delete()
return Response({'code': 100, 'msg': '删除成功'})
在我们的serializer.py文件中编写反序列化的校验
# 全局钩子 # 校验过后的数据,价格不能超过90
def validate(self, attrs):
if int(attrs.get('price')) >= 90:
raise ValidationError('书价格不能超过90')
else:
return attrs
# 局部钩子 校验名字不能以1开头
def validate_name(self, name):
if name.startswith('1'):
raise ValidationError('不能以1开头')
else:
return name
如果满足上述函数报错条件,serializer_obj.is_valid() 不成立!
原生的request 没有data 属性 实现一个原生的 request.data
拿出无论什么编码格式提交的数据(编写FBV即可)
views.py
def method(func):
def inner(request,*args,**kwargs):
try:
# 如果报错说明数据不是Json格式
request.data = request.body
except:
request.data = request.POST
res = func(request)
return res
return inner
@method
def login(request):
print(request.data)
print(request.content_type)
return render(request,'login.html',locals())
最后此篇关于ApiView/Request类源码分析/序列化器的文章就讲到这里了,如果你想了解更多关于ApiView/Request类源码分析/序列化器的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
内容概要 ApiView+JsonResponse编写接口 ApiView+Response编写接口 ApiView源码解析 Request对象源码分析
我正在使用 Django Rest Framework 并使用 APIView 和序列化器形式添加新数据。我想在表单中添加一些帮助文本作为工具提示。由于表单是自动生成的,我需要一些帮助来了解如何将其添
我制作了一个 API 并想制作 swagger 文档。我不为此开发任何序列化。 Views.py class DeliveryView(APIView): renderer_classes =
我正在使用 Django 和 Django-Rest-Framework 为一个与学校相关的小型项目编写 API。我正在尝试找出权限。 我正在为我的 View 使用 APIView,并希望在不编写更多
我正在使用 Django 和 Django-Rest-Framework 为一个与学校相关的小型项目编写 API。我正在尝试找出权限。 我正在为我的 View 使用 APIView,并希望在不编写更多
我试图了解 vb.net 中的一些 WinAPI,但找不到用于 vb6 的 API 查看器工具。 VS2015 有没有更简单的东西? 是否有类似的方法将 WinAPI 代码从工具导入到 vb.net
我正在使用 APIView用于获取和发布项目。 我想使用 Django Rest Framework 为我的 API 实现分页,但它不起作用。 我想每页显示 10 个项目,但是当我这样做时 api/v
我需要更新 code字段与 patch APIView 中的方法. 到目前为止我有这个: class UserDetailView(APIView): def patch(self, requ
我正在尝试使用 Django Rest Framework 制作 APIView。当我将 View 与 url 相关联时,出现此错误: AssertionError: basename argumen
有什么区别APIView 类(class)和 View 集类(class) ? 我正在关注 Django REST-framework官方文档。我认为它缺乏示例。 你能用一个合适的例子来解释上面的区别
我是 Django 新手,我对 Django apiview 的自定义方法有点困惑。在ApiView中,如何创建自定义方法以及如何从axios调用。 例如 这是我的观点 class TimeSheet
我正在尝试将 Swagger 集成到我的 Django Rest Framework API 中。我安装了相关的软件包并按照 Github 页面的快速入门指南进行操作。不过我遇到了一些问题。 Swag
我有一个 APIView 类,用于显示所有租金以及发布和删除等。现在我想要搜索功能,所以我尝试使用 DjangoFilterBackend,但它不起作用。我在文档中看到,它已与 ListAPIView
我有一个权限类来检查 obj.account 是否等于 request.user.profile.account: class IsOwner(permissions.BasePermission):
有什么优势 View 集 , 模型 View 集 和 APIView . django-rest-framework 文档中没有说清楚,也没有说什么时候使用ViewSet、ModelViewSet和A
我正在尝试将 json 数据发布到我的 Django Rest Framework APIView。当我使用 DRF api 发布表单时一切正常,但是当我尝试使用外部应用程序(在我的例子中是 Angu
假设我想在 APIView.get 中返回一个包含 2 个属性的(非模型)对象,其中一个是模型对象,另一个是二进制图像 我尝试了几种方法,但在序列化程序方面遇到了问题。 谢谢! 序列化器: class
在 Django Rest Framework 中,是否可以在 APIView 类中调用自定义方法,类似于 .get() 或 .post() 将被调用。 我知道路由器可以使用 @action() 或
我有一个非常简单的APIView,但我不知道如何在这里设置分页。在这种情况下,我选择一个具有给定 pk 的 Event,然后我获得分配给此 Event 的所有 NewsItems。 paginatio
从下面看。我试图强制交易回滚。但是没有工作。数据仍然插入到数据库中。谁能给我正确的方法? class DocumentDetailView(APIView): def post(sel
我是一名优秀的程序员,十分优秀!